Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
7dfac97
WIP checker: refuse T? == T (EqualityOptionalityMismatch)
Oct 3, 2026
4197312
C4: install regenerated seed; compile_clean census knows EqualityOpti…
Oct 4, 2026
1fb57a4
G: data rows keep their declared ? (preserve_outer_optional_cardinali…
Oct 4, 2026
c0f8fc0
C4: std.filesystem is_text_readable compares the symlink target as Pr…
Oct 4, 2026
1ab6431
G: import preserve_outer_optional_cardinality from v1.std.core
Oct 4, 2026
dd28d25
C4: make the five remaining T? == T sites explicit (.first() and inde…
Oct 4, 2026
1c9bf79
G: move the rationale to module-item grain (a body annotation is refu…
Oct 4, 2026
deee2b8
list index realized as the optional it is typed as (Rust): explicit a…
Oct 4, 2026
d3edf71
G: restore a data annotation's authored ? at resolve, not in the emitter
Oct 4, 2026
84206df
Merge remote-tracking branch 'origin/main' into session/still-raven-3…
Oct 4, 2026
479e1e3
G: the named-refinement arm of emit_data_def keeps the row's declared ?
Oct 4, 2026
93e1d24
tokenizer: keep string-body and escape scans single self-recursive fu…
Oct 4, 2026
60eefa0
G: regenerated v1_compiler_emit_rust.rs
Oct 4, 2026
2e264a7
stage0: regenerate infer, languages and tokenize mirrors (fixed point…
Oct 4, 2026
f12169a
floor_cost_distribution: percentile note at declaration grain
Oct 4, 2026
788be84
G (body): an Optional in a data row is spelled as the target's native…
Oct 4, 2026
a2d87de
floor roster: retire proc_mountinfo#length as ImportsFixed (the index…
Oct 4, 2026
bc09c14
G: regenerated v1_compiler_emit.rs
Oct 4, 2026
c231bd1
floor_cost_distribution: bind the row's module as row_module (module …
Oct 4, 2026
b699fc4
Merge origin/main (infer mirror to be regenerated)
Oct 4, 2026
a0b56f4
infer mirror: start from main's generation (regenerated next)
Oct 4, 2026
4f3f7ad
stage0: regenerate the infer mirror on the merged tree (fixed point a…
Oct 4, 2026
0ab4603
Merge origin/main: native emission controls keep both the filesystem …
Oct 4, 2026
ee77adb
Merge origin/main into G (mirror taken from main; regenerated in the …
Oct 4, 2026
59b5231
G: regenerate v1_compiler_emit_rust.rs over merged main
Oct 4, 2026
b6d8c55
G (review): select the native-option serializer by the row's declared…
Oct 4, 2026
9c036e2
G (review): named predicate for the declared-optional test; collision…
Oct 4, 2026
8dbe7fc
Merge origin/main: native emission controls keep the effectful fold-s…
Oct 4, 2026
804fe94
G (review): regenerated mirrors for the declared-cardinality serializer
Oct 4, 2026
b00ac98
Merge 2I (#13196) into C4: floor_cost_distribution takes 2I's explici…
Oct 4, 2026
01f9489
C4: complexity arg_name_at as a match; C5: refuse a bare T body under…
Oct 4, 2026
bcec7d7
C5: compiler-error test in the seed's established spelling
Oct 4, 2026
c8ac465
C4/C5: regenerated infer and complexity mirrors (seed is a fixed poin…
Oct 4, 2026
b0cf68a
C5: one declared-optional authority for both cardinality directions; …
Oct 4, 2026
8be9316
Revert "C5: one declared-optional authority for both cardinality dire…
Oct 4, 2026
11f3ddc
Revert "C5: compiler-error test in the seed's established spelling"
Oct 4, 2026
99998f1
Revert "C4: complexity arg_name_at as a match; C5: refuse a bare T bo…
Oct 4, 2026
b05cab4
C4: complexity arg_name_at comparisons as a match (re-applied without…
Oct 4, 2026
648e348
C4: regenerated infer mirror without C5 (seed is a fixed point under …
Oct 4, 2026
8300385
C5: re-apply the declared-return mirror predicate and REDs (diagnosis…
Oct 4, 2026
3039c76
C5: a resolved type with no inferred field is concrete, not generic
Oct 4, 2026
f7c380c
C5: regenerated infer mirror (seed is a fixed point under the return …
Oct 4, 2026
3980c8f
Merge origin/main into C5 for the corpus census (infer mirror regener…
Oct 4, 2026
58c4669
C5: regenerated infer mirror over merged main
Oct 4, 2026
e86fbba
C5: running_release_member_string answers Present { value: s } for a …
Oct 4, 2026
2c469d7
Merge origin/main into G (batch 2; mirrors regenerated next)
Oct 5, 2026
034324d
G: regenerate emit mirrors over merged main (batch 2; fixed point)
Oct 5, 2026
efa6874
G (review 76684): exercise the inner-type arm; stop claiming collisio…
Oct 5, 2026
d21f6ec
G (review 76684): a bare inner-type literal under T? refuses instead …
Oct 5, 2026
e033c9b
G: regenerated v1_compiler_emit.rs for the bare-inner-type refusal (f…
Oct 5, 2026
7a01784
Merge origin/main (with #13196) into C4; mirrors regenerated next
Oct 5, 2026
bebc5ed
Merge origin/main (with #13196) into G; regenerated next
Oct 5, 2026
ca9bfc5
G: restore optional_data_row_cases' closing bracket lost in the merge…
Oct 5, 2026
9c914ec
C4: bootstrap v1_std_core.rs = main's copy plus C4's EqualityOptional…
Oct 5, 2026
f39b718
G: pin the bare-lift refusal with an enrolled expected-refusal witnes…
Oct 5, 2026
ab6793a
C4: regenerate infer mirror over main with #13196 (fixed point)
Oct 5, 2026
8c59723
Merge C4 (with main and #13196) into C5; infer mirror regenerated next
Oct 5, 2026
27fc5ba
C5: regenerate infer mirror over C4 + main with #13196 (fixed point)
Oct 5, 2026
0519df0
C5: refuse a bare T data initializer under a declared T? (ruling A on…
Oct 5, 2026
a6852b6
G (ruling A): the bare-lift arm is the exhaustive refusal, unreachabl…
Oct 5, 2026
e862920
C5: regenerated infer mirror for the data-initializer wall (fixed point)
Oct 5, 2026
c9b71b0
C5 (review 76818): position_is_declared_return -> position_forbids_ba…
Oct 6, 2026
51ff800
C5: regenerated infer mirror for the rename (fixed point)
Oct 6, 2026
f5b1edb
C5 (review 76904): refuse a match that mixes a bare arm and an option…
Oct 6, 2026
9580f9d
C5: regenerated infer mirror for the match-arm wall (fixed point)
Oct 6, 2026
acdceaf
C5 (review, 9580f9d6ae): typed DeclaredTypeNotInhabited at the arm; o…
Oct 6, 2026
44f997f
C5 (review 76923): own failure-mode row for the bare-lift walls; cens…
Oct 6, 2026
54cb52a
C5: regenerated infer mirror for the typed match-arm diagnostic (fixe…
Oct 6, 2026
bea7b24
C5: the two genuine corpus sites the match-arm wall refuses (oci laye…
Oct 6, 2026
c6f33b6
C5 ruling B: the match-arm wall's claimed scope excludes the Present-…
Oct 6, 2026
c51af47
C5 ruling B: bind the variant name (a string-literal variant-pattern …
Oct 6, 2026
61efdc6
C5 ruling B: regenerated infer mirror (fixed point)
Oct 6, 2026
ce5d253
C5: scope the Present-payload exclusion to the bare-vs-optional check…
Oct 6, 2026
ab3ef39
C5: regenerated infer mirror for the scoped exclusion (fixed point)
Oct 6, 2026
d69ccd7
C5: the disjoint control asserts the proven-disjoint refusal itself (…
Oct 6, 2026
45bc6f5
Merge main into C5 (test file: kept C5's additions; infer/complexity …
Oct 7, 2026
9abd396
Regenerate stage0 mirrors after merging main into C5 (merge+regen only)
Oct 7, 2026
b4f4873
Merge C5 (and main) into G; mirrors taken from C5, regenerated next
Oct 7, 2026
c2eef2f
Regenerate stage0 mirrors after merging C5 and main into G
Oct 7, 2026
dbfab5b
Merge main into session/still-raven-321-g (mirrors to be regenerated)
Oct 8, 2026
a116850
Close optional_data_row_cases after the merge join
Oct 8, 2026
19b1d3c
Regenerate emit_rust mirror for optional data rows keep ?
Oct 8, 2026
9328c9c
Merge main into #13202; mirrors reset to main for regeneration
Oct 9, 2026
019cbc4
Regenerate emit and emit_rust mirrors after merging main
Oct 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion dag/gunbc/instruments/native_emission_controls.dag
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,38 @@ fn filter_in_branch_condition_cases() -> List<NativeEmissionCase> {
]
}

// RULE: a data row keeps its declared `?`, in its signature and in its body (v1.compiler.emit_rust
// emit_data_def's named-refinement arm; v1.compiler.emit emit_optional_data_value_json). A
// where-refinement such as NonEmptyStr took the one arm of emit_data_def with no optional wrap, so
// gunbc.fleet_tailnet fleet_tailnet_domain (`NonEmptyStr? = Present { .. }`) was emitted
// `-> NonEmptyStr`; and the JSON body spelled Present as a tagged map the native option cannot
// parse.
// Both optional rows pass through a `T?`-typed parameter, so a dropped `?` stops this closure
// compiling, and a wrong body stops it at run time; the cases decide each row answers as declared.
data control_optional_brand_present: NonEmptyStr? = Present { value: "tailnet.example" }

data control_optional_brand_absent: NonEmptyStr? = none

fn control_optional_brand_value(d: NonEmptyStr?) -> String {
match d {
Present { value: v } => v
Absent => ""
}
}

fn optional_data_row_cases() -> List<NativeEmissionCase> {
[
NativeEmissionCase {
identity: "optional_data_row_present_answers_its_value",
held: control_optional_brand_value(d: control_optional_brand_present) == "tailnet.example"
},
NativeEmissionCase {
identity: "optional_data_row_red_absent_answers_absent",
held: control_optional_brand_value(d: control_optional_brand_absent) == ""
}
]
}

// RULE: a data row takes the JSON serializer only when its value is a literal tree
// (v1.compiler.emit_rust data_value_is_json_literal_tree). A `"x" as NonEmptyStr` brand cast, bare or
// inside a record literal, and an operator inside a record literal used to reach the serializer and
Expand Down Expand Up @@ -535,6 +567,8 @@ data native_emission_expected_identities: List<String> = [
"list_index_past_the_end_is_absent",
"list_index_negative_is_absent",
"list_index_into_empty_is_absent",
"optional_data_row_present_answers_its_value",
"optional_data_row_red_absent_answers_absent",
"generic_return_full_arm_answers_its_value",
"generic_return_red_empty_arm_answers_empty",
"generic_return_effectful_call_answers_empty_on_absent_path",
Expand All @@ -543,7 +577,7 @@ data native_emission_expected_identities: List<String> = [
]

fn native_emission_cases() -> List<NativeEmissionCase> {
concat(concat(concat(concat(concat(same_leaf_declaration_cases(), concat(concat(concat(concat(concat(concat(header_bound_cases(), fn_value_bound_cases()), filter_in_branch_condition_cases()), claim_driver_filesystem_cases()), effectful_fold_step_cases()), capability_alias_output_cases()), fold_accumulator_formals_cases())), list_index_cases()), effectful_generic_return_cases()), generic_empty_map_turbofish_cases()), data_literal_tree_cases())
concat(concat(concat(concat(concat(concat(same_leaf_declaration_cases(), concat(concat(concat(concat(concat(concat(header_bound_cases(), fn_value_bound_cases()), filter_in_branch_condition_cases()), claim_driver_filesystem_cases()), effectful_fold_step_cases()), capability_alias_output_cases()), fold_accumulator_formals_cases())), list_index_cases()), optional_data_row_cases()), effectful_generic_return_cases()), generic_empty_map_turbofish_cases()), data_literal_tree_cases())
}

fn case_row(c: NativeEmissionCase) -> String {
Expand Down
43 changes: 43 additions & 0 deletions src/v1/05_emit.dag
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,49 @@ fn emit_data_fields_json(value: Node, source_indices: Map<String, NewlineIndex>,
)
}

// A DATA ROW DECLARED `T?` IS SPELLED AS THE TARGET'S NATIVE OPTION, selected by the row's DECLARED
// cardinality -- never by the spelling of a variant's parent. Every target realizes `T?` natively
// (Rust Option, Python None, Go nil), and each one's JSON reading of it is transparent: absent is
// `null`, present is the payload itself. The caller (v1.compiler.emit_rust emit_data_def_body) asks
// this only for a row whose declared type carries CardOptional, so an unrelated coproduct that happens
// to be NAMED Optional keeps its own wire policy (review on gunbc#13202: a leaf-name test here was a
// second, unrostered authority that would have serialized such a coproduct as null or a bare payload).
// Within an optional row, a variant literal whose parent IS the declared inner type is a bare T under
// T?: an implicit lift no declared coercion admits. That arm REFUSES, and it is the refusal exhaustive
// matching requires -- NOT coverage. It is unreachable: v1.compiler.infer refuses a bare T data
// initializer under a declared T? (the C5 wall, optional_at_required_obligation_diags at
// PositionDataInitializer), and an accepted row of that shape takes the typed-expression path, never
// this serializer (measured on gunbc#13202). Any other one-field variant literal is the option's
// present arm and is unwrapped to its payload. Control: gunbc.instruments.native_emission_controls optional_data_row_cases
// -- the present and absent rows. A coproduct merely NAMED Optional
// cannot be emitted at all today (type rendering decides host-option by leaf name); that case is
// lane 2K's RED, not covered here. Neither refusal arm (a bare inner-type literal, a present literal
// with more than one field) is coverage of anything; both exist only so the match is exhaustive.
fn emit_declared_optional_row_json(value: Node, inner_type_name: String, source_indices: Map<String, NewlineIndex>, variant_wire: Map<String, DataVariantWireSpelling>) -> EmitterOutcome {
match value.expr_data {
ExprLiteral { value: LitNull } => Emitted { json: "null" }
ExprRecordLit { parent_enum: pe } =>
match pe {
Present { value: parent } =>
if qualified_last_segment(name: parent) == qualified_last_segment(name: inner_type_name) {
Refused { reason: concat("a data row declared ", inner_type_name, "? is initialized with a bare ", inner_type_name, " literal: no declared coercion lifts T into T? (DESIGN 4, 2026-09-26), so spell it Present { value: .. } or none") }
} else {
match value.children |> first {
Absent => Emitted { json: "null" }
Present { value: payload_field } =>
if (value.children |> count) == 1 {
emit_data_value_json(value: field_init_node_value(n: payload_field), source_indices: source_indices, variant_wire: variant_wire)
} else {
Refused { reason: concat("an optional row's present literal carries ", to_string(value.children |> count), " fields; the option's present arm carries exactly its payload") }
}
}
}
Absent => emit_data_value_json(value: value, source_indices: source_indices, variant_wire: variant_wire)
}
_ => emit_data_value_json(value: value, source_indices: source_indices, variant_wire: variant_wire)
}
}

fn emit_data_value_json(value: Node, source_indices: Map<String, NewlineIndex>, variant_wire: Map<String, DataVariantWireSpelling>) -> EmitterOutcome {
match value.expr_data {
ExprLiteral { value: v } => match v {
Expand Down
23 changes: 20 additions & 3 deletions src/v1/05_emit_rust.dag
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ import v1.compiler.emit {
emit_lambda_params, emit_null_coalesce, emit_list_lit_expr, emit_shared_expr,
emit_typed_cast_shared, emit_string_literal, emit_simple_expr, escape_rust_interp_text,
module_emit_scope, scope_after_expr, lookup_item_by_identity, has_nested_records_node,
emit_data_value_json, EmitterOutcome, Emitted, Refused, is_null_coalesce, has_service_items,
emit_data_value_json, emit_declared_optional_row_json, EmitterOutcome, Emitted, Refused, is_null_coalesce, has_service_items,
order_typed_call_args_from_semantics, is_tco_eligible, is_self_recursive, emit_shared_tco_expr,
tco_reassign_core, shared_tco_reassign, tco_loop_slot_name, tco_loop_iteration_lets, service_fallback_transport,
effective_operation_transport, ServiceFieldSet, compute_service_fields, service_field_decls,
Expand Down Expand Up @@ -17432,6 +17432,13 @@ fn data_def_annotation_is_named_refinement(annotation: Node, source_indices: Map
// declared type decided by the carrier and its wrap decided by the spelling, and needs_rc is
// threaded into emit_data_def_body, so the value took the same answer as the signature. Routed to
// the carrier authority; the spelling key is deleted rather than kept beside it.
// A NAMED REFINEMENT ROW KEEPS ITS DECLARED `?`. A where-refinement such as std.types NonEmptyStr
// resolves to a Conj carrying its base as one child, so it fails preserves_declared_brand's
// childless test and is rendered by the named-refinement arm -- the one arm that rendered through
// coerce_primitive_type without rust_carrier_optional_wrap. gunbc.fleet_tailnet
// fleet_tailnet_domain (`NonEmptyStr? = Present { .. }`) was emitted `-> NonEmptyStr` and its
// consumer refused E0308. The control is gunbc.instruments.native_emission_controls
// optional_data_row_cases.
fn emit_data_def(name: String, type_node: Node, value: Node, registry: Map<String, ItemInfo>, scope: InferScope, depth: Int, shared_types: Set<String>, emit_info: EmitGraphInfo) -> String {
let ambiguous_annotation_head = v1_type_exprs_ambiguous_declared_head(type_exprs: [type_node], type_decl_items: emit_info.type_decl_items, source_indices: scope.type_env.source_indices)
if ambiguous_annotation_head != "" {
Expand All @@ -17453,7 +17460,7 @@ fn emit_data_def(name: String, type_node: Node, value: Node, registry: Map<Strin
let raw_ty_str = if preserves_declared_brand {
rust_ground_opaque_kernel_type_name(name: ann_name)
} else if data_def_annotation_is_named_refinement(annotation: annotation_type_node, source_indices: scope.type_env.source_indices) {
coerce_primitive_type(decision: type_reference_realization(n: annotation_type_node, dag_name: authored_name_at(source_indices: scope.type_env.source_indices, node: annotation_type_node), target: Rust), dag_name: authored_name_at(source_indices: scope.type_env.source_indices, node: annotation_type_node))
rust_carrier_optional_wrap(n: annotation_type_node, rendered: coerce_primitive_type(decision: type_reference_realization(n: annotation_type_node, dag_name: authored_name_at(source_indices: scope.type_env.source_indices, node: annotation_type_node), target: Rust), dag_name: authored_name_at(source_indices: scope.type_env.source_indices, node: annotation_type_node)))
} else {
render_rust_type_with_applied_binding(n: render_type_node, shared_types: shared_types, source_indices: scope.type_env.source_indices, env: scope.type_env)
}
Expand Down Expand Up @@ -17521,6 +17528,11 @@ fn data_row_type_forbids_deserialize(type_node: Node, emit_info: EmitGraphInfo,
type_expr_reaches_sealed_carrier(n: type_node, emit_info: emit_info, source_indices: source_indices, seen: empty_map())
}

// Named rather than inlined because `if x == Variant {` parses as a record literal in .dag.
fn data_row_declares_optional(type_node: Node) -> Bool {
type_node.return_cardinality == CardOptional
}

fn emit_data_def_body(type_node: Node, value: Node, registry: Map<String, ItemInfo>, scope: InferScope, depth: Int, shared_types: Set<String>, emit_info: EmitGraphInfo, needs_rc: Bool) -> String {
let raw_ty_str = render_rust_type(n: type_node, shared_types: shared_types, source_indices: scope.type_env.source_indices, emit_info: emit_info)
let type_name = authored_name_at(source_indices: scope.type_env.source_indices, node: type_node)
Expand Down Expand Up @@ -17579,7 +17591,12 @@ fn emit_data_def_body(type_node: Node, value: Node, registry: Map<String, ItemIn
} else if match value.expr_data { ExprElaboratedLiteral { value: _, elaboration: _ } => true _ => false } {
concat(" ", emit_typed_expr(texpr: value, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024))
} else if has_nested_records_node(n: type_node, source_indices: scope.type_env.source_indices) && data_value_is_json_literal_tree(value: value) && !data_row_type_forbids_deserialize(type_node: type_node, emit_info: emit_info, source_indices: scope.type_env.source_indices) {
match emit_data_value_json(value: value, source_indices: scope.type_env.source_indices, variant_wire: emit_info.data_variant_wire_spellings) {
let row_json = if data_row_declares_optional(type_node: type_node) {
emit_declared_optional_row_json(value: value, inner_type_name: authored_name_at(source_indices: scope.type_env.source_indices, node: type_node), source_indices: scope.type_env.source_indices, variant_wire: emit_info.data_variant_wire_spellings)
} else {
emit_data_value_json(value: value, source_indices: scope.type_env.source_indices, variant_wire: emit_info.data_variant_wire_spellings)
}
match row_json {
Refused { reason: r } => concat(" compile_error!(\"", escape_string_literal_body(s: r), "\")")
Emitted { json: json_str } => concat(" serde_json::from_str(\"", escape_string_literal_body(s: json_str), "\")\n",
" .expect(\"valid data definition\")")
Expand Down
58 changes: 58 additions & 0 deletions src/v1/stage0/src/v1_compiler_emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,64 @@ pub fn emit_data_fields_json(
)
}

pub fn emit_declared_optional_row_json(
value: Rc<Node>,
inner_type_name: String,
source_indices: Rc<HashMap<String, Rc<NewlineIndex>>>,
variant_wire: Rc<HashMap<String, Rc<DataVariantWireSpelling>>>,
) -> Rc<EmitterOutcome> {
match (*value.expr_data.clone()).clone() {
ExprData::ExprLiteral { ref value, .. }
if matches!(value.as_ref(), LiteralValue::LitNull) =>
{
let LiteralValue::LitNull = value.as_ref() else {
unreachable!()
};
Rc::new(EmitterOutcome::Emitted {
json: "null".to_string(),
})
}
ExprData::ExprRecordLit {
parent_enum: pe, ..
} => match pe.clone() {
Some(parent) => {
if (crate::v1_std_core::qualified_last_segment(parent.clone())
== crate::v1_std_core::qualified_last_segment(inner_type_name.clone()))
{
Rc::new(EmitterOutcome::Refused {
reason: v1_rt::concat(v1_rt::concat(v1_rt::concat(v1_rt::concat("a data row declared ".to_string(), inner_type_name.clone()), "? is initialized with a bare ".to_string()), inner_type_name.clone()), " literal: no declared coercion lifts T into T? (DESIGN 4, 2026-09-26), so spell it Present { value: .. } or none".to_string()),
})
} else {
match value.children.clone().first().cloned() {
std::option::Option::None => Rc::new(EmitterOutcome::Emitted {
json: "null".to_string(),
}),
Some(payload_field) => {
if ((value.children.clone().len() as i64) == 1) {
emit_data_value_json(
crate::v1_std_core::field_init_node_value(
payload_field.clone(),
),
source_indices.clone(),
variant_wire.clone(),
)
} else {
Rc::new(EmitterOutcome::Refused {
reason: v1_rt::concat(v1_rt::concat("an optional row's present literal carries ".to_string(), crate::v1_compiler_emit_core_support::to_string((value.children.clone().len() as i64))), " fields; the option's present arm carries exactly its payload".to_string()),
})
}
}
}
}
}
std::option::Option::None => {
emit_data_value_json(value.clone(), source_indices.clone(), variant_wire.clone())
}
},
_ => emit_data_value_json(value.clone(), source_indices.clone(), variant_wire.clone()),
}
}

pub fn emit_data_value_json(
value: Rc<Node>,
source_indices: Rc<HashMap<String, Rc<NewlineIndex>>>,
Expand Down
Loading
Loading