diff --git a/src/v1/05_emit_rust.dag b/src/v1/05_emit_rust.dag index 6d433a677cd..8c594e53038 100644 --- a/src/v1/05_emit_rust.dag +++ b/src/v1/05_emit_rust.dag @@ -2035,20 +2035,77 @@ fn emit_inferred_type_leaf_name(n: Node, source_indices: Map) -> List { +fn anonymous_record_lit_surface_name(n: Node, source_indices: Map, type_summaries: Map) -> String { + let lit_field_names = n.children |> map(f => field_init_node_name_at(n: f, source_indices: source_indices)) + let field_type_hints = fold(n.children, init: empty_map(), f: (acc, f) => + let fname = field_init_node_name_at(n: f, source_indices: source_indices) + let fval = field_init_node_value(n: f) + match fval.inferred { + Present { value: Resolved { node: type_node } } => + map_insert(acc, fname, authored_name_at(source_indices: source_indices, node: type_node)) + _ => acc + } + ) + match find_struct_name_by_fields(field_names: lit_field_names, field_type_hints: field_type_hints, type_summaries: type_summaries) { + Present { value: sn } => sn + Absent => + match find_unique_struct_name_by_fields(field_names: lit_field_names, type_summaries: type_summaries) { + Present { value: sn } => sn + Absent => + let rt = resolved_type(n: n) + let rt_name = authored_name_at(source_indices: source_indices, node: rt) + if rt.ident_span != none && map_contains_key(type_summaries, rt_name) { rt_name } else { "" } + } + } +} + +fn record_lit_variant_payload_struct_surfaces(n: Node, source_indices: Map, type_summaries: Map, variant_to_enum: Map) -> List { + let variant_name = match record_lit_type_name_at(texpr: n, source_indices: source_indices) { + Present { value: v } => v + Absent => authored_name_at(source_indices: source_indices, node: n) + } + if variant_name == "" { [] } else { + let enum_name = match map_get(variant_to_enum, variant_name) { + Present { value: e } => e + Absent => "" + } + if enum_name == "" { [] } else { + match map_get(type_summaries, variant_summary_key(enum_name: enum_name, variant_name: variant_name)) { + Present { value: summary } => + map_values(summary.field_type_map) |> filter(ft => + ft != "" && match map_get(type_summaries, ft) { + Present { value: fts } => + match fts.repr { + StructRepr => true + _ => false + } + Absent => false + } + ) + Absent => [] + } + } + } +} + +fn record_lit_ref_names(n: Node, source_indices: Map, type_summaries: Map, variant_to_enum: Map) -> List { match n.expr_data { ExprRecordLit { parent_enum: pe } => let tn_list = match record_lit_type_name_at(texpr: n, source_indices: source_indices) { Present { value: t } => if t != "" { [t] } else { [] } Absent => let inferred = emit_inferred_type_leaf_name(n: n, source_indices: source_indices) - if inferred != "" { [inferred] } else { [] } + if inferred != "" { [inferred] } else { + let anon = anonymous_record_lit_surface_name(n: n, source_indices: source_indices, type_summaries: type_summaries) + if anon != "" { [anon] } else { [] } + } } let pe_list = match pe { Present { value: p } => if p != "" { [p] } else { [] } Absent => [] } - unique_strings(items: concat(tn_list, pe_list)) + let payload_structs = record_lit_variant_payload_struct_surfaces(n: n, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum) + unique_strings(items: concat(concat(tn_list, pe_list), payload_structs)) _ => [] } } @@ -2057,7 +2114,18 @@ fn collect_items_field_import_surface_names(items: List, type_summaries: M unique_strings(items: items |> flat_map(item => collect_item_emit_surface_names(item: item, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries) |> flat_map(type_name => - match map_get(type_summaries, type_name) { + let summary_lookup = match map_get(type_summaries, type_name) { + Present { value: summary } => Present { value: summary } + Absent => + match map_get(variant_to_enum, type_name) { + Present { value: enum_name } => + if enum_name == "" { none } else { + map_get(type_summaries, variant_summary_key(enum_name: enum_name, variant_name: type_name)) + } + Absent => none + } + } + match summary_lookup { Present { value: summary } => summary.field_import_surface_names |> filter(field_type => field_type != "" && match map_get(type_summaries, field_type) { @@ -2075,7 +2143,7 @@ fn collect_items_field_import_surface_names(items: List, type_summaries: M )) } -fn collect_value_ref_names(n: Node, source_indices: Map) -> List { +fn collect_value_ref_names(n: Node, source_indices: Map, type_summaries: Map, variant_to_enum: Map) -> List { let self_name = match n.expr_data { ExprVar { binding_kind: bk } => match bk { @@ -2088,24 +2156,24 @@ fn collect_value_ref_names(n: Node, source_indices: Map) - let nm = authored_name_at(source_indices: source_indices, node: n) if nm != "" { [nm] } else { [] } ExprRecordLit { parent_enum: _ } => - record_lit_ref_names(n: n, source_indices: source_indices) + record_lit_ref_names(n: n, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum) _ => [] } let list_fields = concat( concat( - n.children |> flat_map(c => collect_value_ref_names(n: c, source_indices: source_indices)), - n.params |> flat_map(c => collect_value_ref_names(n: c, source_indices: source_indices)) + n.children |> flat_map(c => collect_value_ref_names(n: c, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum)), + n.params |> flat_map(c => collect_value_ref_names(n: c, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum)) ), concat( - n.uses |> flat_map(c => collect_value_ref_names(n: c, source_indices: source_indices)), - n.properties |> flat_map(c => collect_value_ref_names(n: c, source_indices: source_indices)) + n.uses |> flat_map(c => collect_value_ref_names(n: c, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum)), + n.properties |> flat_map(c => collect_value_ref_names(n: c, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum)) ) ) let opt_fields = concat( - match n.body { Present { value: b } => collect_value_ref_names(n: b, source_indices: source_indices) Absent => [] }, + match n.body { Present { value: b } => collect_value_ref_names(n: b, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum) Absent => [] }, concat( - match n.transport { Present { value: t } => collect_value_ref_names(n: t, source_indices: source_indices) Absent => [] }, - match n.type_annotation { Present { value: t } => collect_value_ref_names(n: t, source_indices: source_indices) Absent => [] } + match n.transport { Present { value: t } => collect_value_ref_names(n: t, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum) Absent => [] }, + match n.type_annotation { Present { value: t } => collect_value_ref_names(n: t, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum) Absent => [] } ) ) concat(self_name, concat(list_fields, opt_fields)) @@ -2147,9 +2215,62 @@ fn collect_match_pattern_parent_enums(expr: Node, source_indices: Map, variant_to_enum: Map) -> String { + match n.expr_data { + ExprRecordLit { parent_enum: pe } => + let variant_name = match record_lit_type_name_at(texpr: n, source_indices: source_indices) { + Present { value: v } => v + Absent => authored_name_at(source_indices: source_indices, node: n) + } + let enum_name = match pe { + Present { value: e } => e + Absent => + match map_get(variant_to_enum, variant_name) { + Present { value: p } => p + Absent => "" + } + } + if enum_name != "" && variant_name != "" { + variant_summary_key(enum_name: enum_name, variant_name: variant_name) + } else { "" } + _ => "" + } +} + +fn collect_record_lit_field_struct_surfaces(parent: Node, field_init: Node, source_indices: Map, type_summaries: Map, variant_to_enum: Map) -> List { + let field_name = field_init_node_name_at(n: field_init, source_indices: source_indices) + if field_name == "" { [] } else { + let field_value = field_init_node_value(n: field_init) + match field_value.expr_data { + ExprRecordLit { parent_enum: _ } => + let summary_key = variant_record_lit_summary_key(n: parent, source_indices: source_indices, variant_to_enum: variant_to_enum) + if summary_key == "" { [] } else { + match map_get(type_summaries, summary_key) { + Present { value: summary } => + match map_get(summary.field_type_map, field_name) { + Present { value: ft } => + if ft != "" && match map_get(type_summaries, ft) { + Present { value: fts } => + match fts.repr { + StructRepr => true + _ => false + } + Absent => false + } { [ft] } else { [] } + Absent => [] + } + Absent => [] + } + } + _ => [] + } + } +} + fn collect_value_emit_type_surface_names(n: Node, source_indices: Map, variant_to_enum: Map, type_summaries: Map) -> List { let self_names = match n.expr_data { - ExprRecordLit { parent_enum: _ } => record_lit_ref_names(n: n, source_indices: source_indices) + ExprRecordLit { parent_enum: _ } => + record_lit_ref_names(n: n, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum) ExprMatch => collect_match_pattern_parent_enums(expr: n, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries) _ => let from_inferred = emit_inferred_type_leaf_name(n: n, source_indices: source_indices) @@ -2161,16 +2282,24 @@ fn collect_value_emit_type_surface_names(n: Node, source_indices: Map flat_map(c => collect_value_emit_type_surface_names(n: c, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)), - n.params |> flat_map(c => collect_value_emit_type_surface_names(n: c, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)) - ), - concat( - n.uses |> flat_map(c => collect_value_emit_type_surface_names(n: c, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)), - n.properties |> flat_map(c => collect_value_emit_type_surface_names(n: c, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)) - ) - ) + let child_names = match n.expr_data { + ExprRecordLit { parent_enum: _ } => + concat( + n.children |> flat_map(c => collect_record_lit_field_struct_surfaces(parent: n, field_init: c, source_indices: source_indices, type_summaries: type_summaries, variant_to_enum: variant_to_enum)), + n.children |> flat_map(c => collect_value_emit_type_surface_names(n: field_init_node_value(n: c), source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)) + ) + _ => + concat( + concat( + n.children |> flat_map(c => collect_value_emit_type_surface_names(n: c, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)), + n.params |> flat_map(c => collect_value_emit_type_surface_names(n: c, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)) + ), + concat( + n.uses |> flat_map(c => collect_value_emit_type_surface_names(n: c, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)), + n.properties |> flat_map(c => collect_value_emit_type_surface_names(n: c, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries)) + ) + ) + } let opt_names = concat( match n.body { Present { value: b } => collect_value_emit_type_surface_names(n: b, source_indices: source_indices, variant_to_enum: variant_to_enum, type_summaries: type_summaries) Absent => [] }, concat( @@ -2209,12 +2338,38 @@ fn imported_names_in_use_line(line: String) -> List { data reference_derived_use_lines_note: String = "emit_import_closure_root (§5). emit_imports wires a per-module use-line only for names in an authored import list. Namespace-only resolution (post-PR 6848) references cross-module names WITHOUT importing them, so the ref is KNOWN but the use-line is declined (advisory UnlistedImportUse, is_error_diagnostic=false) — a §5 fail-open (⊤-as-ignorance) that emits invalid Rust (E0422/E0433/E0425 downstream). This pass derives the missing use-lines from the SAME resolver signal, split by reference kind onto its precise authority (§2 Realization: one closure, two consumers): (1) TYPE refs come from the resolver's UnlistedImportUse diagnostics (04_resolve.dag resolve_node, masked && not-in-SVN at type positions) threaded through ResolvedGraph.diagnostics — zero-drift by construction, the resolver already applied its SVN mask AT RESOLVE TIME; (2) VALUE-position refs come from collect_value_ref_names, a NARROW walk that structurally excludes the type over-collection classes (container heads, field labels, deep-inferred type names): fn/data refs (FunctionValueBinding ExprVar + ExprCall callee names) AND record-literal type constructions (ExprRecordLit type name + its parent_enum) — the latter matter because a GENERIC user type constructed as `T{..}` (e.g. RealizedStep) is grounded by resolve_node (masked flips false into the defining-module descent) so it NEVER fires UnlistedImportUse, yet its bare `T` still needs a use-line; (3) TYPE-surface refs on item signatures come from collect_item_emit_surface_names (collect_item_type_surface_names + collect_value_emit_type_surface_names over data bodies) over each item's type_annotation, param types, inferred Resolved return/signature, AND value-position record-literal / variant-parent-enum surfaces the emitter will qualify (e.g. UriScheme::Https in a data anchor) — covering masked-at-resolve TYPE positions (e.g. partial-import return type PilotWidget) that never enter UnlistedImportUse and are not ExprVar/ExprCall harvests. Registry cross-module resolve + is_known_variant fallback keep variant constructors routed through their parent's import. CONSTRUCTION WALL (ROOT 3, §5): a candidate that registry-resolves to a provider module MUST also pass provider_proven_exports_symbol (name_in_transitive_export_surface) before any use-line is synthesized — never a plausible guess from the bare-name registry alone (the v1_rt::member fabrication class: registry homonym without export proof). NOTE the SVN authority is resolve-time-only: env.source_visible_names is built in 04_infer's unresolved_env and consumed by resolve_node, but is NOT persisted onto TypedModule.type_env (emit reads empty_map), so emit MUST NOT re-apply an SVN filter — it would be a no-op that (worse, when non-empty) diverges from the resolve-time mask. The union is instead already-imported filtered (a name already carried by an authored import / prelude / carrier use-line is skipped — this is what keeps a fully-imported SEED module zero-drift: its refs are all in an import line) and kernel filtered (no E0252 against the runtime prelude), then LOCAL-DECL filtered (any name the module itself declares — local_decl_names from authored_name_at over items, plus local_type_names aliases/phantoms — is never an import candidate: the containment tree binds a bare ref to the module's own declaration before any cross-module lookup, and the bare-name registry is last-write-wins, so a dual-tree homonym — dag/std List/Map/GroupCompletion vs their src/v2/std twins — steals the registry row and would otherwise synthesize a SELF-COLLIDING pub-use, the E0255 std_dup class measured on the 2026-07-22 curated 4-module baseline), then cross-module registry-resolved (a ref the registry maps to this same module is skipped), then reuses emit_specific_import_block for variant/reexport correctness with a §5 direct-emit fallback (arm (c): the name resolved via registry to provider AND export-proven). A candidate that registry-resolves to nothing, or resolves but fails export proof, is left unsynthesized (typed refusal at step-2 is future work); it never fabricates a use-line. SCOPE (emit_module_full): import-free modules run the full union (TYPE unlisted + VALUE refs) — the namespace-resolution case the post-PR-6848 regression is about. Import-bearing modules run reference_derived_use_lines ONLY when corpus_repr_is_faithful (FaithfulFreeMonoid / v2 namespace corpus): a partial-import namespace module (e.g. v2.std.node_query importing Outcome but calling outcome_with_diagnostics, or importing Outcome but annotating NamedEdgeTargetLookup) must synthesize BOTH the missing fn-value use-line AND the missing type use-line without duplicating names emit_imports already owns. HostNative import-bearing modules (v1 seed) get [] — running the walk there adds spurious/wrong use-lines (registry homonyms like kernel_span/is_type_variable) and breaks zero-drift seed regen." +fn expand_variant_payload_struct_imports(names: List, type_summaries: Map, variant_to_enum: Map) -> List { + names |> flat_map(n => + match map_get(variant_to_enum, n) { + Present { value: enum_name } => + if enum_name == "" { [] } else { + match map_get(type_summaries, variant_summary_key(enum_name: enum_name, variant_name: n)) { + Present { value: summary } => + map_values(summary.field_type_map) |> filter(ft => + ft != "" && match map_get(type_summaries, ft) { + Present { value: fts } => + match fts.repr { + StructRepr => true + _ => false + } + Absent => false + } + ) + Absent => [] + } + } + Absent => [] + } + ) +} + fn reference_derived_use_lines(items: List, unlisted_type_names: List, this_module_name: String, registry: Map, emit_info: EmitGraphInfo, local_type_names: List, already_imported_names: List, export_sets: Map>, typed_modules: List, source_indices: Map, module_index: ModuleIndex) -> List { { - let value_names = unique_strings(items: items |> flat_map(item => collect_value_ref_names(n: item, source_indices: source_indices))) + let value_names = unique_strings(items: items |> flat_map(item => collect_value_ref_names(n: item, source_indices: source_indices, type_summaries: emit_info.type_summaries, variant_to_enum: emit_info.variant_to_enum))) let type_surface_names = unique_strings(items: items |> flat_map(item => collect_item_emit_surface_names(item: item, source_indices: source_indices, variant_to_enum: emit_info.variant_to_enum, type_summaries: emit_info.type_summaries))) let field_surface_names = collect_items_field_import_surface_names(items: items, type_summaries: emit_info.type_summaries, variant_to_enum: emit_info.variant_to_enum, source_indices: source_indices) - let candidates = unique_strings(items: concat(concat(concat(unlisted_type_names, value_names), type_surface_names), field_surface_names)) + let variant_payload_structs = expand_variant_payload_struct_imports(names: type_surface_names, type_summaries: emit_info.type_summaries, variant_to_enum: emit_info.variant_to_enum) + let candidates = unique_strings(items: concat(concat(concat(concat(unlisted_type_names, value_names), type_surface_names), field_surface_names), variant_payload_structs)) let local_decl_names = items |> flat_map(item => let nm = authored_name_at(source_indices: source_indices, node: item) if nm == "" { [] } else { [nm] } diff --git a/src/v1/stage0/src/v1_compiler_emit_rust.rs b/src/v1/stage0/src/v1_compiler_emit_rust.rs index 60648f55925..49d29dfbb1c 100644 --- a/src/v1/stage0/src/v1_compiler_emit_rust.rs +++ b/src/v1/stage0/src/v1_compiler_emit_rust.rs @@ -4655,9 +4655,122 @@ pub fn emit_inferred_type_leaf_name( } } +pub fn anonymous_record_lit_surface_name( + n: Rc, + source_indices: Rc>>, + type_summaries: Rc>>, +) -> String { + { + let lit_field_names = Rc::new({ + let mut __result = Vec::new(); + for f in n.children.clone().iter().cloned() { + __result.push(field_init_node_name_at(f.clone(), source_indices.clone())); + } + __result + }); + let field_type_hints = n.children.clone().iter().cloned().fold( + v1_rt::rc_empty_map::(), + |acc: Rc>, f: Rc| { + let fname = field_init_node_name_at(f.clone(), source_indices.clone()); + let fval = field_init_node_value(f.clone()); + match fval.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { + node: type_node, .. + }) => v1_rt::rc_map_insert( + acc.clone(), + fname.clone(), + authored_name_at(source_indices.clone(), type_node.clone()), + ), + _ => acc.clone(), + } + }, + ); + match find_struct_name_by_fields( + lit_field_names.clone(), + field_type_hints.clone(), + type_summaries.clone(), + ) { + Some(sn) => sn.clone(), + None => match find_unique_struct_name_by_fields( + lit_field_names.clone(), + type_summaries.clone(), + ) { + Some(sn) => sn.clone(), + None => { + let rt = resolved_type(n.clone()); + let rt_name = authored_name_at(source_indices.clone(), rt.clone()); + if ((rt.ident_span.clone() != None) + && v1_rt::map_contains_key(&type_summaries, rt_name.clone())) + { + rt_name.clone() + } else { + "".to_string() + } + } + }, + } + } +} + +pub fn record_lit_variant_payload_struct_surfaces( + n: Rc, + source_indices: Rc>>, + type_summaries: Rc>>, + variant_to_enum: Rc>, +) -> Rc> { + { + let variant_name = match record_lit_type_name_at(n.clone(), source_indices.clone()) { + Some(v) => v.clone(), + None => authored_name_at(source_indices.clone(), n.clone()), + }; + if (variant_name.clone() == "".to_string()) { + Rc::new(vec![]) + } else { + { + let enum_name = match v1_rt::map_get(&variant_to_enum, variant_name.clone()) { + Some(e) => e.clone(), + None => "".to_string(), + }; + if (enum_name.clone() == "".to_string()) { + Rc::new(vec![]) + } else { + match v1_rt::map_get( + &type_summaries, + variant_summary_key(enum_name.clone(), variant_name.clone()), + ) { + Some(summary) => Rc::new({ + let mut __result = Vec::new(); + for ft in Rc::new(v1_rt::map_values(&summary.field_type_map.clone())) + .iter() + .cloned() + { + if ((ft.clone() != "".to_string()) + && match v1_rt::map_get(&type_summaries, ft.clone()) { + Some(fts) => match (*fts.repr.clone()).clone() { + TypeRepr::StructRepr => true, + _ => false, + }, + None => false, + }) + { + __result.push(ft); + } + } + __result + }), + None => Rc::new(vec![]), + } + } + } + } + } +} + pub fn record_lit_ref_names( n: Rc, source_indices: Rc>>, + type_summaries: Rc>>, + variant_to_enum: Rc>, ) -> Rc> { match (*n.expr_data.clone()).clone() { ExprData::ExprRecordLit { @@ -4676,7 +4789,18 @@ pub fn record_lit_ref_names( if (inferred.clone() != "".to_string()) { Rc::new(vec![inferred.clone()]) } else { - Rc::new(vec![]) + { + let anon = anonymous_record_lit_surface_name( + n.clone(), + source_indices.clone(), + type_summaries.clone(), + ); + if (anon.clone() != "".to_string()) { + Rc::new(vec![anon.clone()]) + } else { + Rc::new(vec![]) + } + } } } }; @@ -4690,7 +4814,16 @@ pub fn record_lit_ref_names( } None => Rc::new(vec![]), }; - unique_strings(v1_rt::concat(tn_list.clone(), pe_list.clone())) + let payload_structs = record_lit_variant_payload_struct_surfaces( + n.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + ); + unique_strings(v1_rt::concat( + v1_rt::concat(tn_list.clone(), pe_list.clone()), + payload_structs.clone(), + )) } _ => Rc::new(vec![]), } @@ -4718,30 +4851,58 @@ pub fn collect_items_field_import_surface_names( .cloned() { __result.extend( - (*match v1_rt::map_get(&type_summaries, type_name.clone()) { - Some(summary) => Rc::new({ - let mut __result = Vec::new(); - for field_type in - summary.field_import_surface_names.clone().iter().cloned() - { - if ((field_type.clone() != "".to_string()) - && match v1_rt::map_get( - &type_summaries, - field_type.clone(), - ) { - Some(ft) => match (*ft.repr.clone()).clone() { - TypeRepr::StructRepr => true, - _ => false, - }, - None => false, - }) + (*{ + let summary_lookup = + match v1_rt::map_get(&type_summaries, type_name.clone()) { + Some(summary) => Some(summary.clone()), + None => match v1_rt::map_get( + &variant_to_enum, + type_name.clone(), + ) { + Some(enum_name) => { + if (enum_name.clone() == "".to_string()) { + None + } else { + v1_rt::map_get( + &type_summaries, + variant_summary_key( + enum_name.clone(), + type_name.clone(), + ), + ) + } + } + None => None, + }, + }; + match summary_lookup.clone() { + Some(summary) => Rc::new({ + let mut __result = Vec::new(); + for field_type in summary + .field_import_surface_names + .clone() + .iter() + .cloned() { - __result.push(field_type); + if ((field_type.clone() != "".to_string()) + && match v1_rt::map_get( + &type_summaries, + field_type.clone(), + ) { + Some(ft) => match (*ft.repr.clone()).clone() { + TypeRepr::StructRepr => true, + _ => false, + }, + None => false, + }) + { + __result.push(field_type); + } } - } - __result - }), - None => Rc::new(vec![]), + __result + }), + None => Rc::new(vec![]), + } }) .iter() .cloned(), @@ -4760,6 +4921,8 @@ pub fn collect_items_field_import_surface_names( pub fn collect_value_ref_names( n: Rc, source_indices: Rc>>, + type_summaries: Rc>>, + variant_to_enum: Rc>, ) -> Rc> { stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { let self_name = match (*n.expr_data.clone()).clone() { @@ -4784,9 +4947,12 @@ pub fn collect_value_ref_names( Rc::new(vec![]) } } - ExprData::ExprRecordLit { parent_enum: _, .. } => { - record_lit_ref_names(n.clone(), source_indices.clone()) - } + ExprData::ExprRecordLit { parent_enum: _, .. } => record_lit_ref_names( + n.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + ), _ => Rc::new(vec![]), }; let list_fields = v1_rt::concat( @@ -4795,9 +4961,14 @@ pub fn collect_value_ref_names( let mut __result = Vec::new(); for c in n.children.clone().iter().cloned() { __result.extend( - (*collect_value_ref_names(c.clone(), source_indices.clone())) - .iter() - .cloned(), + (*collect_value_ref_names( + c.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + )) + .iter() + .cloned(), ); } __result @@ -4806,9 +4977,14 @@ pub fn collect_value_ref_names( let mut __result = Vec::new(); for c in n.params.clone().iter().cloned() { __result.extend( - (*collect_value_ref_names(c.clone(), source_indices.clone())) - .iter() - .cloned(), + (*collect_value_ref_names( + c.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + )) + .iter() + .cloned(), ); } __result @@ -4819,9 +4995,14 @@ pub fn collect_value_ref_names( let mut __result = Vec::new(); for c in n.uses.clone().iter().cloned() { __result.extend( - (*collect_value_ref_names(c.clone(), source_indices.clone())) - .iter() - .cloned(), + (*collect_value_ref_names( + c.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + )) + .iter() + .cloned(), ); } __result @@ -4830,9 +5011,14 @@ pub fn collect_value_ref_names( let mut __result = Vec::new(); for c in n.properties.clone().iter().cloned() { __result.extend( - (*collect_value_ref_names(c.clone(), source_indices.clone())) - .iter() - .cloned(), + (*collect_value_ref_names( + c.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + )) + .iter() + .cloned(), ); } __result @@ -4841,16 +5027,31 @@ pub fn collect_value_ref_names( ); let opt_fields = v1_rt::concat( match n.body.clone() { - Some(b) => collect_value_ref_names(b.clone(), source_indices.clone()), + Some(b) => collect_value_ref_names( + b.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + ), None => Rc::new(vec![]), }, v1_rt::concat( match n.transport.clone() { - Some(t) => collect_value_ref_names(t.clone(), source_indices.clone()), + Some(t) => collect_value_ref_names( + t.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + ), None => Rc::new(vec![]), }, match n.type_annotation.clone() { - Some(t) => collect_value_ref_names(t.clone(), source_indices.clone()), + Some(t) => collect_value_ref_names( + t.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + ), None => Rc::new(vec![]), }, ), @@ -4950,6 +5151,93 @@ pub fn collect_match_pattern_parent_enums( } } +pub fn variant_record_lit_summary_key( + n: Rc, + source_indices: Rc>>, + variant_to_enum: Rc>, +) -> String { + match (*n.expr_data.clone()).clone() { + ExprData::ExprRecordLit { + parent_enum: pe, .. + } => { + let variant_name = match record_lit_type_name_at(n.clone(), source_indices.clone()) { + Some(v) => v.clone(), + None => authored_name_at(source_indices.clone(), n.clone()), + }; + let enum_name = match pe.clone() { + Some(e) => e.clone(), + None => match v1_rt::map_get(&variant_to_enum, variant_name.clone()) { + Some(p) => p.clone(), + None => "".to_string(), + }, + }; + if ((enum_name.clone() != "".to_string()) && (variant_name.clone() != "".to_string())) { + variant_summary_key(enum_name.clone(), variant_name.clone()) + } else { + "".to_string() + } + } + _ => "".to_string(), + } +} + +pub fn collect_record_lit_field_struct_surfaces( + parent: Rc, + field_init: Rc, + source_indices: Rc>>, + type_summaries: Rc>>, + variant_to_enum: Rc>, +) -> Rc> { + { + let field_name = field_init_node_name_at(field_init.clone(), source_indices.clone()); + if (field_name.clone() == "".to_string()) { + Rc::new(vec![]) + } else { + { + let field_value = field_init_node_value(field_init.clone()); + match (*field_value.expr_data.clone()).clone() { + ExprData::ExprRecordLit { parent_enum: _, .. } => { + let summary_key = variant_record_lit_summary_key( + parent.clone(), + source_indices.clone(), + variant_to_enum.clone(), + ); + if (summary_key.clone() == "".to_string()) { + Rc::new(vec![]) + } else { + match v1_rt::map_get(&type_summaries, summary_key.clone()) { + Some(summary) => match v1_rt::map_get( + &summary.field_type_map.clone(), + field_name.clone(), + ) { + Some(ft) => { + if ((ft.clone() != "".to_string()) + && match v1_rt::map_get(&type_summaries, ft.clone()) { + Some(fts) => match (*fts.repr.clone()).clone() { + TypeRepr::StructRepr => true, + _ => false, + }, + None => false, + }) + { + Rc::new(vec![ft.clone()]) + } else { + Rc::new(vec![]) + } + } + None => Rc::new(vec![]), + }, + None => Rc::new(vec![]), + } + } + } + _ => Rc::new(vec![]), + } + } + } + } +} + pub fn collect_value_emit_type_surface_names( n: Rc, source_indices: Rc>>, @@ -4958,9 +5246,12 @@ pub fn collect_value_emit_type_surface_names( ) -> Rc> { stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { let self_names = match (*n.expr_data.clone()).clone() { - ExprData::ExprRecordLit { parent_enum: _, .. } => { - record_lit_ref_names(n.clone(), source_indices.clone()) - } + ExprData::ExprRecordLit { parent_enum: _, .. } => record_lit_ref_names( + n.clone(), + source_indices.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + ), ExprData::ExprMatch => collect_match_pattern_parent_enums( n.clone(), source_indices.clone(), @@ -4991,33 +5282,18 @@ pub fn collect_value_emit_type_surface_names( )) } }; - let child_names = v1_rt::concat( - v1_rt::concat( + let child_names = match (*n.expr_data.clone()).clone() { + ExprData::ExprRecordLit { parent_enum: _, .. } => v1_rt::concat( Rc::new({ let mut __result = Vec::new(); for c in n.children.clone().iter().cloned() { __result.extend( - (*collect_value_emit_type_surface_names( + (*collect_record_lit_field_struct_surfaces( + n.clone(), c.clone(), source_indices.clone(), - variant_to_enum.clone(), type_summaries.clone(), - )) - .iter() - .cloned(), - ); - } - __result - }), - Rc::new({ - let mut __result = Vec::new(); - for c in n.params.clone().iter().cloned() { - __result.extend( - (*collect_value_emit_type_surface_names( - c.clone(), - source_indices.clone(), variant_to_enum.clone(), - type_summaries.clone(), )) .iter() .cloned(), @@ -5025,30 +5301,12 @@ pub fn collect_value_emit_type_surface_names( } __result }), - ), - v1_rt::concat( Rc::new({ let mut __result = Vec::new(); - for c in n.uses.clone().iter().cloned() { - __result.extend( - (*collect_value_emit_type_surface_names( - c.clone(), - source_indices.clone(), - variant_to_enum.clone(), - type_summaries.clone(), - )) - .iter() - .cloned(), - ); - } - __result - }), - Rc::new({ - let mut __result = Vec::new(); - for c in n.properties.clone().iter().cloned() { + for c in n.children.clone().iter().cloned() { __result.extend( (*collect_value_emit_type_surface_names( - c.clone(), + field_init_node_value(c.clone()), source_indices.clone(), variant_to_enum.clone(), type_summaries.clone(), @@ -5060,7 +5318,77 @@ pub fn collect_value_emit_type_surface_names( __result }), ), - ); + _ => v1_rt::concat( + v1_rt::concat( + Rc::new({ + let mut __result = Vec::new(); + for c in n.children.clone().iter().cloned() { + __result.extend( + (*collect_value_emit_type_surface_names( + c.clone(), + source_indices.clone(), + variant_to_enum.clone(), + type_summaries.clone(), + )) + .iter() + .cloned(), + ); + } + __result + }), + Rc::new({ + let mut __result = Vec::new(); + for c in n.params.clone().iter().cloned() { + __result.extend( + (*collect_value_emit_type_surface_names( + c.clone(), + source_indices.clone(), + variant_to_enum.clone(), + type_summaries.clone(), + )) + .iter() + .cloned(), + ); + } + __result + }), + ), + v1_rt::concat( + Rc::new({ + let mut __result = Vec::new(); + for c in n.uses.clone().iter().cloned() { + __result.extend( + (*collect_value_emit_type_surface_names( + c.clone(), + source_indices.clone(), + variant_to_enum.clone(), + type_summaries.clone(), + )) + .iter() + .cloned(), + ); + } + __result + }), + Rc::new({ + let mut __result = Vec::new(); + for c in n.properties.clone().iter().cloned() { + __result.extend( + (*collect_value_emit_type_surface_names( + c.clone(), + source_indices.clone(), + variant_to_enum.clone(), + type_summaries.clone(), + )) + .iter() + .cloned(), + ); + } + __result + }), + ), + ), + }; let opt_names = v1_rt::concat( match n.body.clone() { Some(b) => collect_value_emit_type_surface_names( @@ -5206,6 +5534,59 @@ pub fn reference_derived_use_lines_note() -> String { CACHED.with(|c: &String| c.clone()) } +pub fn expand_variant_payload_struct_imports( + names: Rc>, + type_summaries: Rc>>, + variant_to_enum: Rc>, +) -> Rc> { + Rc::new({ + let mut __result = Vec::new(); + for n in names.clone().iter().cloned() { + __result.extend( + (*match v1_rt::map_get(&variant_to_enum, n.clone()) { + Some(enum_name) => { + if (enum_name.clone() == "".to_string()) { + Rc::new(vec![]) + } else { + match v1_rt::map_get( + &type_summaries, + variant_summary_key(enum_name.clone(), n.clone()), + ) { + Some(summary) => Rc::new({ + let mut __result = Vec::new(); + for ft in + Rc::new(v1_rt::map_values(&summary.field_type_map.clone())) + .iter() + .cloned() + { + if ((ft.clone() != "".to_string()) + && match v1_rt::map_get(&type_summaries, ft.clone()) { + Some(fts) => match (*fts.repr.clone()).clone() { + TypeRepr::StructRepr => true, + _ => false, + }, + None => false, + }) + { + __result.push(ft); + } + } + __result + }), + None => Rc::new(vec![]), + } + } + } + None => Rc::new(vec![]), + }) + .iter() + .cloned(), + ); + } + __result + }) +} + pub fn reference_derived_use_lines( items: Rc>>, unlisted_type_names: Rc>, @@ -5224,9 +5605,14 @@ pub fn reference_derived_use_lines( let mut __result = Vec::new(); for item in items.clone().iter().cloned() { __result.extend( - (*collect_value_ref_names(item.clone(), source_indices.clone())) - .iter() - .cloned(), + (*collect_value_ref_names( + item.clone(), + source_indices.clone(), + emit_info.type_summaries.clone(), + emit_info.variant_to_enum.clone(), + )) + .iter() + .cloned(), ); } __result @@ -5253,12 +5639,20 @@ pub fn reference_derived_use_lines( emit_info.variant_to_enum.clone(), source_indices.clone(), ); + let variant_payload_structs = expand_variant_payload_struct_imports( + type_surface_names.clone(), + emit_info.type_summaries.clone(), + emit_info.variant_to_enum.clone(), + ); let candidates = unique_strings(v1_rt::concat( v1_rt::concat( - v1_rt::concat(unlisted_type_names.clone(), value_names.clone()), - type_surface_names.clone(), + v1_rt::concat( + v1_rt::concat(unlisted_type_names.clone(), value_names.clone()), + type_surface_names.clone(), + ), + field_surface_names.clone(), ), - field_surface_names.clone(), + variant_payload_structs.clone(), )); let local_decl_names = Rc::new({ let mut __result = Vec::new();