diff --git a/dsl/extdeps/cloud/gcp/iam.dag b/dsl/extdeps/cloud/gcp/iam.dag index bb409b1c544..7d73ee000be 100644 --- a/dsl/extdeps/cloud/gcp/iam.dag +++ b/dsl/extdeps/cloud/gcp/iam.dag @@ -11,7 +11,7 @@ module extdeps.cloud.gcp.iam import extdeps.cloud.gcp.gcp { GcpServiceAccount, GcpProject } import extdeps.cloud.gcp.errors { GcpErrorShape } -import std.types { HttpMethod, AuthScheme } +import std.types { HttpMethod, AuthScheme, Secret, ServiceAccountEmail, GcpProjectId, NonEmptyStr } // -- Roles --------------------------------------------------------- diff --git a/dsl/extdeps/cloud/gcp/sts.dag b/dsl/extdeps/cloud/gcp/sts.dag index df71263c373..a4e9d1b30ff 100644 --- a/dsl/extdeps/cloud/gcp/sts.dag +++ b/dsl/extdeps/cloud/gcp/sts.dag @@ -9,7 +9,7 @@ module extdeps.cloud.gcp.sts -import std.types { Url, HttpMethod, AuthScheme } +import std.types { Url, HttpMethod, AuthScheme, Secret, NonEmptyStr } import extdeps.cloud.gcp.errors { GcpErrorShape, GcpOAuth2ErrorShape } import extdeps.github.errors { GitHubErrorShape } diff --git a/src/v2/00_core.dag b/src/v2/00_core.dag index dea1b9c4d5b..96d9249dec0 100644 --- a/src/v2/00_core.dag +++ b/src/v2/00_core.dag @@ -318,9 +318,14 @@ type DeclaredFuncEnv { // Node -- unified recursive structure // ========================================================================= +type BindingId { + value: Int +} + type Node { name: String ident: Int? + binding_id: BindingId? span: SourceSpan ident_span: SourceSpan? children: List @@ -350,6 +355,33 @@ fn node_name_span(n: Node) -> SourceSpan { match n.ident_span { Present { value: s } => s Absent => n.span } } +fn node_with_binding_id(n: Node, binding_id: BindingId) -> Node { + Node { + name: n.name, ident: n.ident, binding_id: Present { value: binding_id }, + span: n.span, ident_span: n.ident_span, children: n.children, + connective: n.connective, params: n.params, inferred: n.inferred, + return_cardinality: n.return_cardinality, uses: n.uses, + body: n.body, transport: n.transport, properties: n.properties, + type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, + has_non_tail_self_call: n.has_non_tail_self_call, + match_pattern: n.match_pattern, expr_data: n.expr_data + } +} + +fn node_with_preserved_binding_id(identity: Node, structural: Node) -> Node { + Node { + name: structural.name, ident: structural.ident, binding_id: identity.binding_id, + span: structural.span, ident_span: structural.ident_span, + children: structural.children, connective: structural.connective, params: structural.params, + inferred: structural.inferred, return_cardinality: structural.return_cardinality, + uses: structural.uses, body: structural.body, transport: structural.transport, + properties: structural.properties, type_annotation: structural.type_annotation, + is_self_recursive: structural.is_self_recursive, + has_non_tail_self_call: structural.has_non_tail_self_call, + match_pattern: structural.match_pattern, expr_data: structural.expr_data + } +} + // Construct a Node carrying expression data (P5.11 dissolved form). // Children are passed explicitly — ExprData is pure operator metadata. fn make_expr_node(expr_data: ExprData, children: List, inferred: InferredNode?, span: SourceSpan) -> Node { @@ -1156,7 +1188,7 @@ fn transport_env(t: Node, source_indices: Map) -> List Node) -> Node { Node { - name: node.name, ident: node.ident, span: node.span, ident_span: node.ident_span, + name: node.name, ident: node.ident, binding_id: node.binding_id, span: node.span, ident_span: node.ident_span, children: node.children |> map(child => transform(child)), connective: node.connective, params: node.params, inferred: node.inferred, @@ -1527,9 +1559,9 @@ fn pre_intern_tokens(tokens: List, table: InternTable) -> InternTable { } fn with_optional_cardinality(n: Node) -> Node { - Node { name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: CardOptional, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + Node { name: n.name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: CardOptional, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } } fn with_required_cardinality(n: Node) -> Node { - Node { name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: Required, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + Node { name: n.name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: Required, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } } diff --git a/src/v2/02_parse.dag b/src/v2/02_parse.dag index 9b71effd5d0..77fb555821c 100644 --- a/src/v2/02_parse.dag +++ b/src/v2/02_parse.dag @@ -42,7 +42,7 @@ import v2.std.core { ShStrBegin, ShStrMid, ShStrEnd, ShNewline, ShEof, ShUnknown, SourceSpan, make_span, - ErrorNode, make_error_node, ParseError, + ErrorNode, make_error_node, ParseError, InternalError, with_required_cardinality, error_type, is_compiler_error, node_name_span, no_span, diff --git a/src/v2/04_env.dag b/src/v2/04_env.dag index 736b0da1283..906add4c51d 100644 --- a/src/v2/04_env.dag +++ b/src/v2/04_env.dag @@ -1,15 +1,34 @@ // v2 type environment -- structural type bindings and lookup. module v2.compiler.infer_env -import v2.std.core { Node, NewlineIndex, InternTable, empty_intern_table, merge_intern_tables, intern, intern_find, intern_str, source_text_at, authored_name_at } +import v2.std.core { BindingId, Node, SourceSpan, NewlineIndex, InternTable, empty_intern_table, merge_intern_tables, intern, intern_find, intern_str, source_text_at, authored_name_at, error_type } import std.induction { InductiveField, RecursionShape, DirectRecursion, ListRecursion, OptionalRecursion, SubValueRelation, SubValueUnknown, PreservedValue } // ========================================================================= // Types // ========================================================================= +// Three binding maps coexist during phase-1 migration: `bindings` is the +// legacy intern-key index for unresolved/name-only lookup; `decl_registry` +// is the authority stamp (BindingId → declaration metadata + binding_key); +// `carrier_bindings` holds imported/hidden structural carriers keyed by +// BindingId when no local decl_registry row exists. `lookup_type_for` +// consults decl_registry first, verifies binding_id on the resolved node, +// and only accepts the legacy intern row when it carries the same BindingId. +// If that intern row is shadowed by another visible same-name import, +// carrier_bindings may still supply the exact BindingId-keyed hidden row; +// without that exact carrier row, lookup returns a compiler error. +// 🟡 tracked scaffold — owner: Mgr-SOUNDNESS; lane: #4587 BindingId phase-2. +// Dissolve when declaration registration stamps every local/imported transparent +// alias through one BindingId-keyed declaration table before lookup: fold +// carrier_bindings into decl_registry-backed rows and demote `bindings` to the +// unresolved pre-registration spelling index only. Forbidden steady state: +// payload-owning parallel maps or spelling fallback for BindingId-stamped nodes. type TypeEnv { bindings: Map + carrier_bindings: Map + decl_registry: Map + duplicate_decl_ids: List recursive_types: List recursive_type_set: Map inductive_fields: Map> @@ -23,6 +42,71 @@ type TypeBinding { provenance: SubValueRelation } +type TypeDeclBinding { + binding_id: BindingId + authority: TypeDeclAuthority + binding_key: Int + decl_arity: Int + name: String + provenance: SubValueRelation +} + +type TypeDeclAuthority { + module_name: String + decl_name: String + decl_span: SourceSpan +} + +type BindingIdAllocator { + next_id: Int +} + +type BindingIdAllocResult { + binding_id: BindingId + allocator: BindingIdAllocator +} + +fn empty_binding_id_allocator() -> BindingIdAllocator { + BindingIdAllocator { next_id: 1 } +} + +fn alloc_binding_id(allocator: BindingIdAllocator) -> BindingIdAllocResult { + BindingIdAllocResult { + binding_id: BindingId { value: allocator.next_id }, + allocator: BindingIdAllocator { next_id: allocator.next_id + 1 } + } +} + +type DeclRegistryMergeState { + decl_registry: Map + duplicate_decl_ids: List +} + +fn merge_decl_registry_state(state: DeclRegistryMergeState, incoming: Map) -> DeclRegistryMergeState { + fold(map_keys(incoming), init: state, f: (acc, binding_id) => + match map_get(incoming, binding_id) { + Present { value: binding } => + match map_get(acc.decl_registry, binding_id) { + Present { value: existing } => + if existing.authority == binding.authority { + acc + } else { + DeclRegistryMergeState { + decl_registry: acc.decl_registry, + duplicate_decl_ids: list_push(acc.duplicate_decl_ids, binding_id) + } + } + Absent => + DeclRegistryMergeState { + decl_registry: map_insert(acc.decl_registry, binding_id, binding), + duplicate_decl_ids: acc.duplicate_decl_ids + } + } + Absent => acc + } + ) +} + // ========================================================================= // Environment operations // ========================================================================= @@ -55,14 +139,95 @@ fn lookup_type_by_name(env: TypeEnv, name: String) -> Node? { } } +fn lookup_decl_arity_for(env: TypeEnv, node: Node) -> Int? { + match node.binding_id { + Present { value: binding_id } => + match map_get(env.decl_registry, binding_id) { + Present { value: decl } => Present { value: decl.decl_arity } + Absent => none + } + Absent => + let node_name = authored_name(env: env, node: node) + let by_ident = match node.ident { + Present { value: id } => + fold(env.decl_registry |> map_values, init: none, f: (acc, decl) => + match acc { + Present { value: _ } => acc + Absent => if decl.binding_key == id { Present { value: decl.decl_arity } } else { none } + } + ) + Absent => none + } + match by_ident { + Present { value: _ } => by_ident + Absent => + fold(env.decl_registry |> map_values, init: none, f: (acc, decl) => + match acc { + Present { value: _ } => acc + Absent => if decl.name == node_name { Present { value: decl.decl_arity } } else { none } + } + ) + } + } +} + +fn lookup_carrier_type_for(env: TypeEnv, node: Node) -> Node? { + match node.binding_id { + Present { value: binding_id } => + match map_get(env.carrier_bindings, binding_id) { + Present { value: binding } => Present { value: binding.resolved } + Absent => none + } + Absent => none + } +} + +fn node_has_binding_id(n: Node, binding_id: BindingId) -> Bool { + match n.binding_id { + Present { value: actual } => actual == binding_id + Absent => false + } +} + +fn lookup_binding_id_type_for(env: TypeEnv, node: Node) -> Node? { + match node.binding_id { + Present { value: binding_id } => + match map_get(env.decl_registry, binding_id) { + Present { value: decl } => + match lookup_type(env: env, ident: decl.binding_key) { + Present { value: resolved } => + if node_has_binding_id(n: resolved, binding_id: binding_id) { + Present { value: resolved } + } else { + match lookup_carrier_type_for(env: env, node: node) { + Present { value: carrier } => Present { value: carrier } + Absent => Present { value: error_type } + } + } + Absent => lookup_carrier_type_for(env: env, node: node) + } + Absent => lookup_carrier_type_for(env: env, node: node) + } + Absent => none + } +} + fn authored_name(env: TypeEnv, node: Node) -> String { authored_name_at(source_indices: env.source_indices, node: node) } fn lookup_type_for(env: TypeEnv, node: Node) -> Node? { - match node.ident { - Present { value: id } => lookup_type(env: env, ident: id) - Absent => lookup_type_by_name(env: env, name: authored_name(env: env, node: node)) + match node.binding_id { + Present { value: _ } => lookup_binding_id_type_for(env: env, node: node) + Absent => + match node.ident { + Present { value: id } => + match lookup_type(env: env, ident: id) { + Present { value: resolved } => Present { value: resolved } + Absent => lookup_type_by_name(env: env, name: authored_name(env: env, node: node)) + } + Absent => lookup_type_by_name(env: env, name: authored_name(env: env, node: node)) + } } } @@ -127,6 +292,14 @@ fn inductive_fields_list_to_map(fields: List) -> Map) -> TypeEnv { let merged_bindings = fold(envs, init: empty_map(), f: (acc, env) => map_merge(acc, env.bindings)) + let merged_carrier_bindings = fold(envs, init: empty_map(), f: (acc, env) => map_merge(acc, env.carrier_bindings)) + let merged_decl_state = fold(envs, init: DeclRegistryMergeState { decl_registry: empty_map(), duplicate_decl_ids: [] }, f: (acc, env) => + let with_prior_duplicates = DeclRegistryMergeState { + decl_registry: acc.decl_registry, + duplicate_decl_ids: concat(acc.duplicate_decl_ids, env.duplicate_decl_ids) + } + merge_decl_registry_state(state: with_prior_duplicates, incoming: env.decl_registry) + ) let merged_recursive = fold(envs, init: [], f: (acc, env) => concat(acc, env.recursive_types)) let merged_recursive_set = fold(envs, init: empty_map(), f: (acc, env) => map_merge(acc, env.recursive_type_set)) let merged_inductive_fields = fold(envs, init: empty_map(), f: (acc, env) => merge_inductive_fields(left: acc, right: env.inductive_fields)) @@ -135,5 +308,5 @@ fn merge_envs(envs: List) -> TypeEnv { Present { value: first_env } => first_env.intern_table Absent => empty_intern_table() } - TypeEnv { bindings: merged_bindings, recursive_types: merged_recursive, recursive_type_set: merged_recursive_set, inductive_fields: merged_inductive_fields, source_indices: merged_source_indices, intern_table: merged_intern_table } + TypeEnv { bindings: merged_bindings, carrier_bindings: merged_carrier_bindings, decl_registry: merged_decl_state.decl_registry, duplicate_decl_ids: merged_decl_state.duplicate_decl_ids, recursive_types: merged_recursive, recursive_type_set: merged_recursive_set, inductive_fields: merged_inductive_fields, source_indices: merged_source_indices, intern_table: merged_intern_table } } diff --git a/src/v2/04_infer.dag b/src/v2/04_infer.dag index a10e0bcec2a..0a8664b1ab1 100644 --- a/src/v2/04_infer.dag +++ b/src/v2/04_infer.dag @@ -2,12 +2,12 @@ module v2.compiler.infer -import std.types { SourceSpan, container_param_name } +import std.types { SourceSpan, container_param_name, kernel_type_set, is_kernel_type, container_template_algebra } import std.coercion { dag_can_cast, is_dag_cast_domain_type } import v2.std.core { Node, InternTable, intern, intern_str, - authored_name_at, NewlineIndex, find_child_named, has_child_named, build_newline_index, + authored_name_at, NewlineIndex, find_child_named, has_child_named, variant_node_fields, build_newline_index, module_node, module_imports, module_items, import_is_all, make_param_node, param_node_name_at, param_node_type_expr, field_node_type_expr, field_node_name_at, @@ -26,7 +26,6 @@ import v2.std.core { ErrorNode, make_error_node, is_error_diagnostic, InternalError, TypeMismatch, VariantCollision, resource_use_name_at, resource_use_resource, - kernel_type_set, is_kernel_type, is_child_accessor_in_model, is_tree_size_reducing, is_property_contraction, expr_has_self_call, expr_has_non_tail_self_call, DeclaredFuncSig, DeclaredFuncEnv, @@ -52,6 +51,7 @@ import v2.std.core { make_transport_node, local_transport_node, Text, Interpolation, with_optional_cardinality, with_required_cardinality, + BindingId, node_with_binding_id, node_with_preserved_binding_id, no_span, make_span, NewlineIndex, unit_type, bool_type, string_type, int_type, float_type, none_type, error_type, @@ -67,7 +67,7 @@ import v2.compiler.infer_types { callable_inferred, normalize_access_type_node, node_type_shape, node_type_compatible, node_type_equals, prefer_specific_type, - is_declared_container_alias_spelling, structural_carrier_template_name, + canonical_template_name, is_declared_container_alias_spelling, structural_carrier_template_name, node_type_deps, method_receiver_element_node, infer_literal_node, infer_binop_type_node, @@ -81,8 +81,9 @@ import v2.compiler.infer_method { } import v2.compiler.infer_cycle { detect_type_cycles_kahn } import v2.compiler.infer_env { - TypeEnv, TypeBinding, - is_recursive_type, is_recursive_type_by_name, lookup_type, lookup_type_by_name, lookup_type_for, merge_envs, + TypeEnv, TypeBinding, TypeDeclBinding, TypeDeclAuthority, BindingIdAllocator, + empty_binding_id_allocator, alloc_binding_id, + is_recursive_type, is_recursive_type_by_name, lookup_type, lookup_type_by_name, lookup_type_for, node_has_binding_id, merge_envs, put_inductive_field, put_inductive_field_cross, merge_inductive_fields, inductive_fields_for, inductive_fields_list_to_map } @@ -101,7 +102,7 @@ import std.termination { import std.algebra { CollectionSizeEffect, ShrinkEffect } import v2.compiler.infer_resolve { resolve_node, resolve_item_types, peel_nominal_alias_identity, preserve_nominal_brand_on_resolve, - NodeResolveResult, ItemResult + peel_nominal_alias_identity_result, NodeResolveResult, ItemResult } import v2.compiler.infer_sigs { ResolvedFuncSig, ResolvedFuncEnv, ResolveFuncSigsResult, @@ -166,18 +167,36 @@ type ModuleContext { svc_registry: Map> locals: Map item_registry: Map + variant_collisions: Map diagnostics: List } type VariantFoldState { locals: Map - collision_errors: List + collisions: Map +} + +fn is_bootstrap_duplicate_variant_name(name: String) -> Bool { + // Bounded bootstrap carve-out for shared external tag names until variant + // constructors carry parent identity through value lookup. Owner/lane: + // Mgr-SOUNDNESS variant-constructor parent-identity dissolution; remove this + // list when variant value lookup keys by parent BindingId instead of child + // spelling. + name == "Rust" || name == "Go" || name == "TreeSize" || name == "Bits32" +} + +fn same_canonical_container_variant_parent(left: Node, right: Node, source_indices: Map) -> Bool { + let left_name = canonical_template_name(n: left, source_indices: source_indices) + let right_name = canonical_template_name(n: right, source_indices: source_indices) + let same_name = left_name == right_name + left.connective == Disj && right.connective == Disj && same_name } type InferScope { type_env: TypeEnv func_env: ResolvedFuncEnv locals: Map + variant_collisions: Map match_bound_names: Map module_name: String service_registry: Map> @@ -264,6 +283,7 @@ type FieldInferResult { type BuildTypeEnvResult { env: TypeEnv + allocator: BindingIdAllocator diagnostics: List } @@ -311,33 +331,43 @@ fn merge_scope_from_imports(remaining: List, parent_index: Map - match map_get(parent_index, imp.module_path) { - Present { value: typed_parent } => - let next_func_sigs = fold(typed_parent.func_env.signatures |> map_values, init: func_sigs, f: (acc, rsig) => - let sig_key = rsig.name - let sig_params = rsig.params - let sig_rt = rsig.inferred - let sig_async = rsig.is_async - map_insert(acc, sig_key, DeclaredFuncSig { - name: sig_key, params: sig_params, - inferred: Present { value: sig_rt }, - is_async: sig_async, - output_provenance: rsig.output_provenance, - variant_provenance: rsig.variant_provenance - }) - ) + match map_get(parent_index, imp.module_path) { + Present { value: typed_parent } => + let next_func_sigs = fold(typed_parent.func_env.signatures |> map_values, init: func_sigs, f: (acc, rsig) => + let sig_key = rsig.name + if import_allows_binding_name(imp: imp, name: sig_key) == false { + acc + } else { + let sig_params = rsig.params |> map(p => + stamp_hidden_dependency_refs(n: p, dep_env: typed_parent.type_env, source_indices: typed_parent.type_env.source_indices) + ) + let sig_rt = stamp_hidden_dependency_refs(n: rsig.inferred, dep_env: typed_parent.type_env, source_indices: typed_parent.type_env.source_indices) + let sig_async = rsig.is_async + map_insert(acc, sig_key, DeclaredFuncSig { + name: sig_key, params: sig_params, + inferred: Present { value: sig_rt }, + is_async: sig_async, + output_provenance: rsig.output_provenance, + variant_provenance: rsig.variant_provenance + }) + } + ) let parent_result = fold(typed_parent.items, init: InferScopeComponents { func_sigs: next_func_sigs, svc_registry: svc_registry, svc_locals: svc_locals }, f: (acc, titem) => - if titem.transport != none && titem.children |> count > 0 { + let item_name = authored_name_at(source_indices: env.source_indices, node: titem) + if import_allows_binding_name(imp: imp, name: item_name) == false { + acc + } + else if titem.transport != none && titem.children |> count > 0 { let entries = titem.children |> map(c => OpEntry { name: authored_name_at(source_indices: env.source_indices, node: c), outputs: inferred_to_outputs(inferred: c.inferred, span: c.span, source_indices: env.source_indices), params: c.params } ) - let root = namespace_root_from_properties(properties: titem.properties, name: authored_name_at(source_indices: env.source_indices, node: titem), source_indices: env.source_indices) + let root = namespace_root_from_properties(properties: titem.properties, name: item_name, source_indices: env.source_indices) InferScopeComponents { func_sigs: acc.func_sigs, - svc_registry: map_insert(acc.svc_registry, authored_name_at(source_indices: env.source_indices, node: titem), entries), + svc_registry: map_insert(acc.svc_registry, item_name, entries), svc_locals: map_insert(acc.svc_locals, root, nominal_type_binding(name: root)) } } @@ -345,7 +375,7 @@ fn merge_scope_from_imports(remaining: List, parent_index: Map InferResult { } } +fn infer_null_literal_node(expected: Node?) -> Node { + match expected { + Present { value: exp } => + match exp.return_cardinality { + CardOptional => exp + _ => infer_literal_node(lit: LitNull) + } + Absent => infer_literal_node(lit: LitNull) + } +} + fn semantic_expr_error_node(message: String, span: SourceSpan) -> Node { make_expr_error_node(kind: SemanticExprError, message: message, span: span) } @@ -497,24 +538,35 @@ fn internal_expr_error_node(message: String, span: SourceSpan) -> Node { make_expr_error_node(kind: InternalExprError, message: message, span: span) } +fn variant_collision_result(name: String, span: SourceSpan, collision: ErrorNode) -> InferResult { + InferResult { + typed: semantic_expr_error_node(message: concat("ambiguous variant '", name, "'"), span: span), + diagnostics: [collision] + } +} + fn lookup_variant_parent_enum(scope: InferScope, name: String) -> String? { // BRIDGE DEBT (M4): uses has_child_named to verify variant membership. // scope.locals contains ALL locals (params, let bindings, match bindings), // not just variant bindings — the Disj check alone is insufficient. // Deletion point: when variant bindings carry a structural parent edge. - match map_get(scope.locals, name) { - Present { value: binding } => - match lookup_type_for(env: scope.type_env, node: binding.resolved) { - Present { value: parent } => - let is_coproduct = parent.connective == Disj - if is_coproduct { - if has_child_named(n: parent, name: name, source_indices: scope.type_env.source_indices) { - Present { value: authored_name_at(source_indices: scope.type_env.source_indices, node: binding.resolved) } - } else { none } - } else { none } + match map_get(scope.variant_collisions, name) { + Present { value: _ } => none + Absent => + match map_get(scope.locals, name) { + Present { value: binding } => + match lookup_type_for(env: scope.type_env, node: binding.resolved) { + Present { value: parent } => + let is_coproduct = parent.connective == Disj + if is_coproduct { + if has_child_named(n: parent, name: name, source_indices: scope.type_env.source_indices) { + Present { value: authored_name_at(source_indices: scope.type_env.source_indices, node: binding.resolved) } + } else { none } + } else { none } + Absent => none + } Absent => none } - Absent => none } } @@ -545,31 +597,69 @@ fn rejects_string_for_optional_coproduct_field(expected: Node, got: Node, source // general record-field type-check path. let expected_inner = with_required_cardinality(n: expected) let expected_is_optional_coproduct = expected.return_cardinality == CardOptional && expected_inner.connective == Disj - let got_is_string = authored_name_at(source_indices: source_indices, node: got) == "String" + let got_is_string = got.name == "String" expected_is_optional_coproduct && got_is_string } -fn record_lit_expected_fields(type_name: String?, scope: InferScope) -> List { +fn expected_coproduct_variant(parent: Node, variant_name: String, source_indices: Map) -> Node? { + match parent.connective { + Disj => find_child_named(n: parent, name: variant_name, source_indices: source_indices) + _ => none + } +} + +fn expected_has_coproduct_variant(expected: Node?, variant_name: String, source_indices: Map) -> Bool { + match expected { + Present { value: expected_node } => + match expected_coproduct_variant(parent: expected_node, variant_name: variant_name, source_indices: source_indices) { + Present { value: _ } => true + Absent => false + } + Absent => false + } +} + +fn record_lit_expected_fields(type_name: String?, scope: InferScope, expected: Node?) -> List { match type_name { Present { value: tn } => - match lookup_type_by_name(env: scope.type_env, name: tn) { - Present { value: direct } => direct.children + match map_get(scope.variant_collisions, tn) { + Present { value: _ } => [] Absent => - match lookup_variant_parent_enum(scope: scope, name: tn) { - Present { value: parent_name } => - match lookup_type_by_name(env: scope.type_env, name: parent_name) { - Present { value: parent } => - match parent.children |> filter(v => authored_name_at(source_indices: scope.type_env.source_indices, node: v) == tn) |> first { - Present { value: variant } => variant.children + match lookup_type_by_name(env: scope.type_env, name: tn) { + Present { value: direct } => direct.children + Absent => + match lookup_variant_parent_enum(scope: scope, name: tn) { + Present { value: parent_name } => + match lookup_type_by_name(env: scope.type_env, name: parent_name) { + Present { value: parent } => + match parent.children |> filter(v => authored_name_at(source_indices: scope.type_env.source_indices, node: v) == tn) |> first { + Present { value: variant } => variant.children + Absent => [] + } Absent => [] } - Absent => [] - } - Absent => [] - } - } - Absent => [] - } + Absent => + match lookup_coproduct_parent_binding_by_variant(env: scope.type_env, variant_name: tn) { + Present { value: parent_binding } => + match expected_coproduct_variant(parent: parent_binding.resolved, variant_name: tn, source_indices: scope.type_env.source_indices) { + Present { value: variant } => variant.children + Absent => [] + } + Absent => + match expected { + Present { value: expected_node } => + match expected_coproduct_variant(parent: expected_node, variant_name: tn, source_indices: scope.type_env.source_indices) { + Present { value: variant } => variant.children + Absent => [] + } + Absent => [] + } + } + } + } + } + Absent => [] + } } type KernelListTyDiag { @@ -629,16 +719,277 @@ fn type_node_is_callable(n: Node) -> Bool { n.params |> count > 0 } -// TRANSITION (A3 / PD-3): compiler substrate (v4.* std + v2.compiler.* self-host) -// models fn-vs-Callable, witness carriers, and symbolic nominal pairs -// (Symbol/GeneratorId, ConfigPatchRecord/patch nodes) outside PD-3 brand scope. -// Bound: prefix match v4.* and v2.compiler.* only — user modules run the hook. -// Dissolution trigger: ROADMAP.md Active Deferrals row PD-3-DOGFOOD -// (delete when v4-lens-ci + v4-m1-rust-emit-probe pass without this skip). +// TRANSITION (A3 / PD-3): no path-based, prefix-based, or module-name bypass. +// Direct-call diagnostics must be justified by typed authored forms and +// declaration identity below. fn module_skips_direct_call_arg_check(module_name: String) -> Bool { - let is_v4 = string_length(s: module_name) >= 3 && substring(s: module_name, start: 0, end: 3) == "v4." - let is_compiler_substrate = string_length(s: module_name) >= 13 && substring(s: module_name, start: 0, end: 13) == "v2.compiler." - is_v4 || is_compiler_substrate + false +} + +fn direct_call_actual_is_none(actual_expr: Node, actual_type: Node, source_indices: Map) -> Bool { + authored_name_at(source_indices: source_indices, node: actual_expr) == "none" + || authored_name_at(source_indices: source_indices, node: actual_type) == "None" +} + +fn direct_call_actual_is_empty_collection(formal_raw: Node, actual_expr: Node, actual_type: Node, source_indices: Map) -> Bool { + authored_name_at(source_indices: source_indices, node: actual_expr) == "Empty" + && node_is_element_collection(n: formal_raw, source_indices: source_indices) + && node_is_element_collection(n: actual_type, source_indices: source_indices) +} + +fn direct_call_arg_is_typed_deferral(formal_raw: Node, actual_expr: Node, actual_type: Node, source_indices: Map) -> Bool { + let formal_is_callable = type_node_is_callable(n: formal_raw) || authored_name_at(source_indices: source_indices, node: formal_raw) == "Callable" + let actual_is_callable_literal = is_lambda_expr(e: actual_expr) + let formal_is_optional = formal_raw.return_cardinality == CardOptional || authored_name_at(source_indices: source_indices, node: formal_raw) == "Optional" + let actual_is_none = direct_call_actual_is_none(actual_expr: actual_expr, actual_type: actual_type, source_indices: source_indices) + let actual_is_empty_collection = direct_call_actual_is_empty_collection(formal_raw: formal_raw, actual_expr: actual_expr, actual_type: actual_type, source_indices: source_indices) + (formal_is_callable && actual_is_callable_literal) || (formal_is_optional && actual_is_none) || actual_is_empty_collection +} + +fn node_contains_type_variable(n: Node) -> Bool { + let inferred_has_type_variable = match n.inferred { + Present { value: TypeVariable { id: _ } } => true + Present { value: Resolved { node: rt } } => node_contains_type_variable(n: rt) + _ => false + } + inferred_has_type_variable + || (n.children |> any(ch => node_contains_type_variable(n: ch))) + || (n.params |> any(p => node_contains_type_variable(n: p))) +} + +fn node_contains_generic_name(n: Node, generic_names: List, source_indices: Map) -> Bool { + let n_name = authored_name_at(source_indices: source_indices, node: n) + let is_generic_leaf = n.connective == NoConnective + && n.children |> count == 0 + && n.params |> count == 0 + && (generic_names |> any(g => g == n_name)) + is_generic_leaf + || (n.children |> any(ch => node_contains_generic_name(n: ch, generic_names: generic_names, source_indices: source_indices))) + || (n.params |> any(p => node_contains_generic_name(n: p, generic_names: generic_names, source_indices: source_indices))) + || match n.inferred { + Present { value: Resolved { node: rt } } => node_contains_generic_name(n: rt, generic_names: generic_names, source_indices: source_indices) + _ => false + } +} + +fn direct_call_arg_decl_identity(n: Node, env: TypeEnv) -> Node { + match n.binding_id { + Present { value: _ } => n + Absent => + match lookup_type_for(env: env, node: n) { + Present { value: resolved } => + let resolved_with_cardinality = with_optional_cardinality(n: resolved) + match n.return_cardinality { + CardOptional => resolved_with_cardinality + _ => resolved + } + Absent => n + } + } +} + +fn direct_call_node_binding(env: TypeEnv, n: Node) -> TypeBinding? { + match n.binding_id { + Present { value: binding_id } => + match map_get(env.decl_registry, binding_id) { + Present { value: decl } => + match map_get(env.bindings, decl.binding_key) { + Present { value: binding } => + if node_has_binding_id(n: binding.resolved, binding_id: binding_id) { + Present { value: binding } + } else { + map_get(env.carrier_bindings, binding_id) + } + Absent => map_get(env.carrier_bindings, binding_id) + } + Absent => map_get(env.carrier_bindings, binding_id) + } + Absent => none + } +} + +fn direct_call_bare_alias_target_name(binding: TypeBinding, source_indices: Map) -> String? { + match direct_call_bare_alias_target_node(binding: binding) { + Present { value: target } => Present { value: authored_name_at(source_indices: source_indices, node: target) } + Absent => none + } +} + +fn direct_call_bare_alias_target_node(binding: TypeBinding) -> Node? { + let resolved = binding.resolved + if resolved.connective == NoConnective && resolved.children |> count == 0 && resolved.params |> count == 0 { + match resolved.inferred { + Present { value: Resolved { node: target } } => + let declared_or_structural_target = target.binding_id != none || target.connective != NoConnective + if declared_or_structural_target { Present { value: target } } else { none } + _ => none + } + } else { none } +} + +fn direct_call_target_matches_alias_target(env: TypeEnv, target_node: Node, alias_target: String) -> Bool { + match target_node.binding_id { + Present { value: binding_id } => + match map_get(env.decl_registry, binding_id) { + Present { value: decl } => decl.name == alias_target + Absent => authored_name_at(source_indices: env.source_indices, node: target_node) == alias_target + } + Absent => authored_name_at(source_indices: env.source_indices, node: target_node) == alias_target + } +} + +fn direct_call_target_matches_alias_target_node(env: TypeEnv, target_node: Node, alias_target_node: Node) -> Bool { + let alias_target_name = authored_name_at(source_indices: env.source_indices, node: alias_target_node) + match alias_target_node.binding_id { + Present { value: alias_target_binding_id } => + match target_node.binding_id { + Present { value: target_binding_id } => target_binding_id == alias_target_binding_id + Absent => false + } + Absent => + alias_target_name != "" && direct_call_target_matches_alias_target(env: env, target_node: target_node, alias_target: alias_target_name) + } +} + +fn direct_call_carrier_transparent_alias_to(env: TypeEnv, alias_node: Node, target_node: Node) -> Bool { + match alias_node.binding_id { + Present { value: alias_binding_id } => + match map_get(env.carrier_bindings, alias_binding_id) { + Present { value: carrier } => + let carrier_target = match direct_call_bare_alias_target_node(binding: carrier) { + Present { value: target } => target + Absent => + let carrier_is_structural_shell = carrier.resolved.connective != NoConnective + || carrier.resolved.children |> count > 0 + || carrier.resolved.params |> count > 0 + let carrier_has_alias_id = match carrier.resolved.binding_id { + Present { value: carrier_binding_id } => carrier_binding_id == alias_binding_id + Absent => false + } + let carrier_name = authored_name_at(source_indices: env.source_indices, node: carrier.resolved) + if carrier_is_structural_shell && carrier_has_alias_id && carrier.name != carrier_name { + match lookup_type_by_name(env: env, name: carrier_name) { + Present { value: resolved_target } => resolved_target + Absent => carrier.resolved + } + } else { + carrier.resolved + } + } + match carrier_target.binding_id { + Present { value: carrier_target_binding_id } => + carrier_target_binding_id != alias_binding_id + && match target_node.binding_id { + Present { value: target_binding_id } => target_binding_id == carrier_target_binding_id + Absent => false + } + Absent => false + } + Absent => false + } + Absent => false + } +} + +fn direct_call_transparent_alias_to(env: TypeEnv, alias_node: Node, target_node: Node) -> Bool { + let target_name = authored_name_at(source_indices: env.source_indices, node: target_node) + if direct_call_carrier_transparent_alias_to(env: env, alias_node: alias_node, target_node: target_node) { true } + else { + match direct_call_node_binding(env: env, n: alias_node) { + Present { value: binding } => + match direct_call_bare_alias_target_node(binding: binding) { + Present { value: alias_target_node } => direct_call_target_matches_alias_target_node(env: env, target_node: target_node, alias_target_node: alias_target_node) + Absent => + let resolved_name = authored_name_at(source_indices: env.source_indices, node: binding.resolved) + let alias_decl_name = match alias_node.binding_id { + Present { value: binding_id } => + match map_get(env.decl_registry, binding_id) { + Present { value: decl } => decl.name + Absent => binding.name + } + Absent => binding.name + } + let declared_or_structural_target = binding.resolved.binding_id != none || binding.resolved.connective != NoConnective + alias_decl_name != resolved_name + && declared_or_structural_target + && direct_call_target_matches_alias_target_node(env: env, target_node: target_node, alias_target_node: binding.resolved) + } + Absent => + // Some transparent bare aliases resolve their binding row to the target's + // BindingId (e.g. ParseTree = Node). Use the alias declaration authority + // plus the raw binding row; do not fall back to arbitrary same-shape nodes. + match alias_node.binding_id { + Present { value: binding_id } => + match map_get(env.decl_registry, binding_id) { + Present { value: decl } => + match map_get(env.bindings, decl.binding_key) { + Present { value: raw_binding } => + let raw_resolved_name = authored_name_at(source_indices: env.source_indices, node: raw_binding.resolved) + let declared_or_structural_target = raw_binding.resolved.binding_id != none || raw_binding.resolved.connective != NoConnective + decl.name != raw_resolved_name + && declared_or_structural_target + && direct_call_target_matches_alias_target_node(env: env, target_node: target_node, alias_target_node: raw_binding.resolved) + Absent => false + } + Absent => false + } + Absent => false + } + } + } +} + +fn direct_call_decl_registry_transparent_alias_to(env: TypeEnv, alias_node: Node, target_node: Node) -> Bool { + let target_name = authored_name_at(source_indices: env.source_indices, node: target_node) + match alias_node.binding_id { + Present { value: binding_id } => + match map_get(env.decl_registry, binding_id) { + Present { value: decl } => + match map_get(env.bindings, decl.binding_key) { + Present { value: raw_binding } => + match direct_call_bare_alias_target_node(binding: raw_binding) { + Present { value: alias_target_node } => + decl.name != target_name + && raw_binding.name == decl.name + && direct_call_target_matches_alias_target_node(env: env, target_node: target_node, alias_target_node: alias_target_node) + Absent => false + } + Absent => false + } + Absent => false + } + Absent => false + } +} + +fn direct_call_transparent_alias_pair(env: TypeEnv, left: Node, right: Node, source_indices: Map) -> Bool { + direct_call_transparent_alias_to(env: env, alias_node: left, target_node: right) + || direct_call_transparent_alias_to(env: env, alias_node: right, target_node: left) + || direct_call_decl_registry_transparent_alias_to(env: env, alias_node: left, target_node: right) + || direct_call_decl_registry_transparent_alias_to(env: env, alias_node: right, target_node: left) +} + +fn direct_call_decl_identity_mismatch( + formal_identity: Node, + actual_identity: Node, + formal: Node, + actual: Node, + env: TypeEnv, + source_indices: Map +) -> Bool { + let formal_container = node_is_element_collection(n: formal, source_indices: source_indices) + let actual_container = node_is_element_collection(n: actual, source_indices: source_indices) + let same_structural_carrier = structural_carrier_template_name(n: formal, source_indices: source_indices) == structural_carrier_template_name(n: actual, source_indices: source_indices) + match formal_identity.binding_id { + Present { value: formal_binding_id } => + match actual_identity.binding_id { + Present { value: actual_binding_id } => + formal_binding_id != actual_binding_id && same_structural_carrier && !formal_container && !actual_container + && !direct_call_transparent_alias_pair(env: env, left: formal_identity, right: actual_identity, source_indices: source_indices) + Absent => false + } + Absent => false + } } // Bounded direct-call arg check (A3 / E1): surface nominal brand mismatches @@ -647,10 +998,18 @@ fn module_skips_direct_call_arg_check(module_name: String) -> Bool { fn nominal_call_arg_brand_mismatch(formal: Node, actual: Node, source_indices: Map) -> Bool { let formal_name = authored_name_at(source_indices: source_indices, node: formal) let actual_name = authored_name_at(source_indices: source_indices, node: actual) + let distinct_brand = match formal.binding_id { + Present { value: formal_binding_id } => + match actual.binding_id { + Present { value: actual_binding_id } => formal_binding_id != actual_binding_id + Absent => formal_name != actual_name + } + Absent => formal_name != actual_name + } formal.connective != Arrow && actual.connective != Arrow && formal_name != "" && actual_name != "" - && formal_name != actual_name + && distinct_brand && structural_carrier_template_name(n: formal, source_indices: source_indices) == structural_carrier_template_name(n: actual, source_indices: source_indices) && !is_declared_container_alias_spelling(name: formal_name) && !is_declared_container_alias_spelling(name: actual_name) @@ -684,9 +1043,65 @@ fn container_element_nominal_brand_mismatch( } else { false } } -// Call-site brand-twin reject only (A3): node_type_compatible stays relation-compat -// (container-alias tolerance at 04_types.dag:738-742); this hook rejects same-carrier -// nominal twins at direct ExprCall sites without widening relation-wide. +fn direct_call_plain_kernel_leaf_mismatch(formal: Node, actual: Node, source_indices: Map) -> Bool { + let formal_name = authored_name_at(source_indices: source_indices, node: formal) + let actual_name = authored_name_at(source_indices: source_indices, node: actual) + formal.binding_id == none + && actual.binding_id == none + && formal.connective == NoConnective + && actual.connective == NoConnective + && formal.children |> count == 0 + && actual.children |> count == 0 + && formal.return_cardinality == Required + && actual.return_cardinality == Required + && is_kernel_type(name: formal_name) + && is_kernel_type(name: actual_name) + && formal_name != actual_name +} + +fn direct_call_element_collection_carrier(n: Node, source_indices: Map) -> Bool { + let name = authored_name_at(source_indices: source_indices, node: n) + let child_count = (n.children |> count) + (node_is_element_collection(n: n, source_indices: source_indices) || is_declared_container_alias_spelling(name: name)) + && child_count == 1 +} + +fn direct_call_product_field_names_match(formal: Node, actual: Node, source_indices: Map) -> Bool { + formal.children |> enumerate |> all(pair => + match actual.children |> skip(pair.first) |> first { + Present { value: actual_field } => + field_node_name_at(n: pair.second, source_indices: source_indices) == field_node_name_at(n: actual_field, source_indices: source_indices) + Absent => false + } + ) +} + +fn direct_call_structural_pd3_mismatch(formal: Node, actual: Node, env: TypeEnv, source_indices: Map) -> Bool { + let same_structural_carrier = structural_carrier_template_name(n: formal, source_indices: source_indices) == structural_carrier_template_name(n: actual, source_indices: source_indices) + let both_declared_identity = formal.binding_id != none && actual.binding_id != none && same_structural_carrier + let both_element_carriers = direct_call_element_collection_carrier(n: formal, source_indices: source_indices) + && direct_call_element_collection_carrier(n: actual, source_indices: source_indices) + && same_structural_carrier + let formal_name = authored_name_at(source_indices: source_indices, node: formal) + let actual_name = authored_name_at(source_indices: source_indices, node: actual) + let formal_child_count = (formal.children |> count) + let actual_child_count = (actual.children |> count) + let record_twin_carriers = formal.connective == Conj + && actual.connective == Conj + && formal_name != "" + && actual_name != "" + && formal_name != actual_name + && formal_child_count > 0 + && formal_child_count == actual_child_count + && direct_call_product_field_names_match(formal: formal, actual: actual, source_indices: source_indices) + (both_declared_identity || both_element_carriers || record_twin_carriers) + && !direct_call_transparent_alias_pair(env: env, left: formal, right: actual, source_indices: source_indices) + && !node_type_compatible(left: formal, right: actual, source_indices: source_indices) +} + +// Direct-call argument gate: compare the resolved formal/actual types through +// node_type_compatible, whose leaf path carries binding_id brand identity and +// whose container-alias path keeps List/FreeMonoid transparency. fn direct_call_arg_type_mismatch( formal: Node, actual: Node, @@ -694,9 +1109,12 @@ fn direct_call_arg_type_mismatch( module_name: String, source_indices: Map ) -> Bool { - if type_node_is_callable(n: formal) || type_node_is_callable(n: actual) { false } + if direct_call_transparent_alias_pair(env: type_env, left: formal, right: actual, source_indices: source_indices) { false } + else if type_node_is_callable(n: formal) || type_node_is_callable(n: actual) { false } else { - nominal_call_arg_brand_mismatch(formal: formal, actual: actual, source_indices: source_indices) + direct_call_structural_pd3_mismatch(formal: formal, actual: actual, env: type_env, source_indices: source_indices) + || direct_call_plain_kernel_leaf_mismatch(formal: formal, actual: actual, source_indices: source_indices) + || nominal_call_arg_brand_mismatch(formal: formal, actual: actual, source_indices: source_indices) || container_element_nominal_brand_mismatch( formal: formal, actual: actual, type_env: type_env, module_name: module_name, source_indices: source_indices) } @@ -706,6 +1124,7 @@ fn direct_call_arg_mismatch_diags( value_params: List, typed_args: List, call_subst: Map, + generic_names: List, type_env: TypeEnv, module_name: String ) -> List { @@ -715,21 +1134,51 @@ fn direct_call_arg_mismatch_diags( pair => let formal_raw = param_node_type_expr(n: pair.second) let formal_subst = substitute_generics(n: formal_raw, subst: call_subst, source_indices: source_indices) - let formal = peel_nominal_alias_identity(n: formal_subst, env: type_env, module_name: module_name) + let formal_peeled_result = peel_nominal_alias_identity_result(n: formal_subst, env: type_env, module_name: module_name) + let formal_peeled = formal_peeled_result.node + let formal_identity = direct_call_arg_decl_identity(n: formal_peeled, env: type_env) + let formal = stamp_hidden_dependency_refs(n: formal_peeled, dep_env: type_env, source_indices: source_indices) match typed_args |> skip(pair.first) |> first { Present { value: ta } => - let actual_raw = resolved_type(n: arg_value(n: ta)) - let actual = peel_nominal_alias_identity(n: actual_raw, env: type_env, module_name: module_name) - if direct_call_arg_type_mismatch( + let actual_expr = arg_value(n: ta) + let actual_raw = resolved_type(n: actual_expr) + let actual_peeled_result = peel_nominal_alias_identity_result(n: actual_raw, env: type_env, module_name: module_name) + let actual_peeled = actual_peeled_result.node + let actual_identity = direct_call_arg_decl_identity(n: actual_peeled, env: type_env) + let actual = stamp_hidden_dependency_refs(n: actual_peeled, dep_env: type_env, source_indices: source_indices) + let peel_diags = concat(formal_peeled_result.diagnostics, actual_peeled_result.diagnostics) + let arg_span = arg_value(n: ta).span + if peel_diags |> count > 0 { + peel_diags + } else if direct_call_arg_is_typed_deferral( + formal_raw: formal_raw, + actual_expr: actual_expr, + actual_type: actual_raw, + source_indices: source_indices + ) || node_contains_type_variable(n: formal_subst) || node_contains_type_variable(n: actual_raw) + || node_contains_generic_name(n: formal_subst, generic_names: generic_names, source_indices: source_indices) + || node_contains_generic_name(n: actual_raw, generic_names: generic_names, source_indices: source_indices) { + [] + } else if direct_call_transparent_alias_pair(env: type_env, left: formal_identity, right: actual_identity, source_indices: source_indices) + || direct_call_transparent_alias_pair(env: type_env, left: formal, right: actual, source_indices: source_indices) { + [] + } else if direct_call_decl_identity_mismatch( + formal_identity: formal_identity, + actual_identity: actual_identity, + formal: formal, + actual: actual, + env: type_env, + source_indices: source_indices + ) || direct_call_arg_type_mismatch( formal: formal, actual: actual, type_env: type_env, module_name: module_name, source_indices: source_indices) { [type_mismatch_error( expected: node_type_shape(n: formal, source_indices: source_indices), got: node_type_shape(n: actual, source_indices: source_indices), - span: arg_value(n: ta).span, + span: arg_span, module_name: module_name )] } else { [] } - Absent => [] + Absent => formal_peeled_result.diagnostics } ) } @@ -1015,13 +1464,14 @@ fn build_params_scope(scope: InferScope, params: List) -> InferScope { let new_locals = fold(params, init: scope.locals, f: (acc, p) => map_insert(acc, param_node_name_at(n: p, source_indices: scope.type_env.source_indices), TypeBinding { name: param_node_name_at(n: p, source_indices: scope.type_env.source_indices), resolved: param_node_type_expr(n: p), provenance: PreservedValue }) ) - InferScope { - type_env: scope.type_env, - func_env: scope.func_env, - locals: new_locals, - match_bound_names: scope.match_bound_names, - module_name: scope.module_name, - service_registry: scope.service_registry, + InferScope { + type_env: scope.type_env, + func_env: scope.func_env, + locals: new_locals, + variant_collisions: scope.variant_collisions, + match_bound_names: scope.match_bound_names, + module_name: scope.module_name, + service_registry: scope.service_registry, item_registry: scope.item_registry, lambda_param_provenance: empty_map() } @@ -1029,26 +1479,28 @@ fn build_params_scope(scope: InferScope, params: List) -> InferScope { fn extend_scope(scope: InferScope, name: String, resolved: Node, provenance: SubValueRelation) -> InferScope { - InferScope { - type_env: scope.type_env, - func_env: scope.func_env, - locals: map_insert(scope.locals, name, TypeBinding { name: name, resolved: resolved, provenance: provenance }), - match_bound_names: scope.match_bound_names, - module_name: scope.module_name, - service_registry: scope.service_registry, + InferScope { + type_env: scope.type_env, + func_env: scope.func_env, + locals: map_insert(scope.locals, name, TypeBinding { name: name, resolved: resolved, provenance: provenance }), + variant_collisions: scope.variant_collisions, + match_bound_names: scope.match_bound_names, + module_name: scope.module_name, + service_registry: scope.service_registry, item_registry: scope.item_registry, lambda_param_provenance: scope.lambda_param_provenance } } fn extend_scope_match_bound(scope: InferScope, name: String, resolved: Node, provenance: SubValueRelation) -> InferScope { - InferScope { - type_env: scope.type_env, - func_env: scope.func_env, - locals: map_insert(scope.locals, name, TypeBinding { name: name, resolved: resolved, provenance: provenance }), - match_bound_names: map_insert(scope.match_bound_names, name, true), - module_name: scope.module_name, - service_registry: scope.service_registry, + InferScope { + type_env: scope.type_env, + func_env: scope.func_env, + locals: map_insert(scope.locals, name, TypeBinding { name: name, resolved: resolved, provenance: provenance }), + variant_collisions: scope.variant_collisions, + match_bound_names: map_insert(scope.match_bound_names, name, true), + module_name: scope.module_name, + service_registry: scope.service_registry, item_registry: scope.item_registry, lambda_param_provenance: scope.lambda_param_provenance } @@ -1058,13 +1510,14 @@ fn extend_scope_with_params(scope: InferScope, params: List) -> InferSco let new_locals = fold(params, init: scope.locals, f: (acc, p) => map_insert(acc, p, TypeBinding { name: p, resolved: type_variable_node(id: "lambda_param"), provenance: SubValueUnknown }) ) - InferScope { - type_env: scope.type_env, - func_env: scope.func_env, - locals: new_locals, - match_bound_names: scope.match_bound_names, - module_name: scope.module_name, - service_registry: scope.service_registry, + InferScope { + type_env: scope.type_env, + func_env: scope.func_env, + locals: new_locals, + variant_collisions: scope.variant_collisions, + match_bound_names: scope.match_bound_names, + module_name: scope.module_name, + service_registry: scope.service_registry, item_registry: scope.item_registry, lambda_param_provenance: scope.lambda_param_provenance } @@ -1146,12 +1599,18 @@ fn extend_scope_with_pattern_node(scope: InferScope, pattern: MatchPattern, scru } fn method_name_is(opt: String?, expected: String) -> Bool { - if opt == none { false } else { opt.value == expected } + match opt { + Present { value: name } => name == expected + Absent => false + } } fn arg_has_name(arg: Node, name: String, source_indices: Map) -> Bool { let n = arg_name_at(n: arg, source_indices: source_indices) - if n == none { false } else { n.value == name } + match n { + Present { value: actual } => actual == name + Absent => false + } } fn extract_fold_init_info(method_name: String?, method_args: List, min_args: Int, scope: InferScope, expected: Node?) -> ArgInferResult? { @@ -1219,13 +1678,14 @@ fn infer_method_args_with_fold(method_name: String?, method_args: List, fo SubValueUnknown => empty_map() _ => map_insert(empty_map(), "elem", elem_provenance) } - let fold_scope = InferScope { - type_env: scope.type_env, - func_env: scope.func_env, - locals: scope.locals, - match_bound_names: scope.match_bound_names, - module_name: scope.module_name, - service_registry: scope.service_registry, + let fold_scope = InferScope { + type_env: scope.type_env, + func_env: scope.func_env, + locals: scope.locals, + variant_collisions: scope.variant_collisions, + match_bound_names: scope.match_bound_names, + module_name: scope.module_name, + service_registry: scope.service_registry, item_registry: scope.item_registry, lambda_param_provenance: prov_map } @@ -1238,13 +1698,14 @@ fn infer_method_args_with_fold(method_name: String?, method_args: List, fo _ => map_insert(empty_map(), "elem", elem_provenance) } let nf_scope = if is_lambda_expr(e: nf_lam_value) { - InferScope { - type_env: scope.type_env, - func_env: scope.func_env, - locals: scope.locals, - match_bound_names: scope.match_bound_names, - module_name: scope.module_name, - service_registry: scope.service_registry, + InferScope { + type_env: scope.type_env, + func_env: scope.func_env, + locals: scope.locals, + variant_collisions: scope.variant_collisions, + match_bound_names: scope.match_bound_names, + module_name: scope.module_name, + service_registry: scope.service_registry, item_registry: scope.item_registry, lambda_param_provenance: nf_prov_map } @@ -1286,74 +1747,123 @@ fn infer_arg_with_element_type(arg: Node, element_type: Node, scope: InferScope) fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { match texpr.expr_data { - ExprLiteral { value: lit } => - let span = texpr.span - ok_infer(texpr: make_expr_node(expr_data: ExprLiteral { value: lit }, children: [], inferred: Present { value: Resolved { node: infer_literal_node(lit: lit) } }, span: span)) + ExprLiteral { value: lit } => + let span = texpr.span + let inferred_lit = match lit { + LitNull => infer_null_literal_node(expected: expected) + _ => infer_literal_node(lit: lit) + } + ok_infer(texpr: make_expr_node(expr_data: ExprLiteral { value: lit }, children: [], inferred: Present { value: Resolved { node: inferred_lit } }, span: span)) - ExprError { kind: kind, message: message } => - let span = texpr.span - InferResult { - typed: make_expr_error_node(kind: kind, message: message, span: span), - diagnostics: [] - } + ExprError { kind: kind, message: message } => + let span = texpr.span + InferResult { + typed: make_expr_error_node(kind: kind, message: message, span: span), + diagnostics: [] + } - ExprVar { binding_kind: _ } => - let name = expr_var_name_at(texpr: texpr, source_indices: scope.type_env.source_indices) - let span = texpr.span - match map_get(scope.locals, name) { - Present { value: binding } => - let binding_kind = infer_var_binding_kind(scope: scope, name: name) - ok_infer(texpr: make_named_expr_node( - name: name, - expr_data: ExprVar { binding_kind: Present { value: binding_kind } }, - children: [], - inferred: Present { value: Resolved { node: binding.resolved } }, - span: span, - name_span: span - )) - Absent => - match lookup_func_sig(func_env: scope.func_env, name: name) { - Present { value: fsig } => - if (fsig.params |> count) == 0 { - ok_infer(texpr: make_named_expr_node( - name: name, - expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, - children: [], - inferred: Present { value: Resolved { node: fsig.inferred } }, - span: span, - name_span: span - )) - } else { - ok_infer(texpr: make_named_expr_node( + ExprVar { binding_kind: _ } => + let name = expr_var_name_at(texpr: texpr, source_indices: scope.type_env.source_indices) + let span = texpr.span + let collision = map_get(scope.variant_collisions, name) + if collision != none { + variant_collision_result(name: name, span: span, collision: collision.value) + } else { + match map_get(scope.locals, name) { + Present { value: binding } => + let binding_kind = infer_var_binding_kind(scope: scope, name: name) + let local_typed = make_named_expr_node( name: name, - expr_data: ExprVar { binding_kind: Present { value: FunctionValueBinding } }, + expr_data: ExprVar { binding_kind: Present { value: binding_kind } }, children: [], - inferred: Present { value: Resolved { node: resolved_callable_type(func_params: fsig.params, ret: fsig.inferred) } }, + inferred: Present { value: Resolved { node: binding.resolved } }, span: span, name_span: span - )) - } - Absent => - let err_texpr = make_named_expr_node( - name: name, - expr_data: ExprVar { binding_kind: none }, - children: [], - inferred: Present { value: Resolved { node: error_type } }, - span: span, - name_span: span - ) - InferResult { - typed: err_texpr, - diagnostics: [inference_error( - message: concat("undefined variable '", name, "'"), - span: span, - module_name: scope.module_name - )] + ) + let expected_local_diags = match expected { + Present { value: expected_node } => + if rejects_string_for_optional_coproduct_field( + expected: expected_node, + got: binding.resolved, + source_indices: scope.type_env.source_indices + ) { + [type_mismatch_error( + expected: node_type_shape(n: expected_node, source_indices: scope.type_env.source_indices), + got: node_type_shape(n: binding.resolved, source_indices: scope.type_env.source_indices), + span: span, + module_name: scope.module_name + )] + } else { [] } + Absent => [] + } + InferResult { + typed: local_typed, + diagnostics: expected_local_diags + } + Absent => + let expected_variant_parent = match expected { + Present { value: expected_node } => + match expected_coproduct_variant(parent: expected_node, variant_name: name, source_indices: scope.type_env.source_indices) { + Present { value: _ } => Present { value: authored_name_at(source_indices: scope.type_env.source_indices, node: expected_node) } + Absent => none + } + Absent => none + } + match expected_variant_parent { + Present { value: parent_enum } => + ok_infer(texpr: make_named_expr_node( + name: name, + expr_data: ExprVar { binding_kind: Present { value: VariantValueBinding { parent_enum: parent_enum } } }, + children: [], + inferred: Present { value: Resolved { node: expected.value } }, + span: span, + name_span: span + )) + Absent => + match lookup_func_sig(func_env: scope.func_env, name: name) { + Present { value: fsig } => + if (fsig.params |> count) == 0 { + ok_infer(texpr: make_named_expr_node( + name: name, + expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, + children: [], + inferred: Present { value: Resolved { node: fsig.inferred } }, + span: span, + name_span: span + )) + } else { + ok_infer(texpr: make_named_expr_node( + name: name, + expr_data: ExprVar { binding_kind: Present { value: FunctionValueBinding } }, + children: [], + inferred: Present { value: Resolved { node: resolved_callable_type(func_params: fsig.params, ret: fsig.inferred) } }, + span: span, + name_span: span + )) + } + Absent => + let err_texpr = make_named_expr_node( + name: name, + expr_data: ExprVar { binding_kind: none }, + children: [], + inferred: Present { value: Resolved { node: error_type } }, + span: span, + name_span: span + ) + InferResult { + typed: err_texpr, + diagnostics: [inference_error( + message: concat("undefined variable '", name, "'"), + span: span, + module_name: scope.module_name + )] + } + } + } } } - } - ExprFieldAccess { summary: _ } => + ExprFieldAccess { summary: _ } => let field_name = field_access_field_at(texpr: texpr, source_indices: scope.type_env.source_indices) let span = texpr.span let base_expr = field_access_base(texpr: texpr) @@ -1440,6 +1950,9 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { Present { value: s } => s.params Absent => [] } + let generic_names = sig_params + |> filter(p => param_is_generic_decl(p: p, source_indices: scope.type_env.source_indices)) + |> map(p => authored_name_at(source_indices: scope.type_env.source_indices, node: param_node_type_expr(n: p))) let has_lambda = call_args |> any(a => is_lambda_expr(e: arg_value(n: a))) let call_method_args = call_args |> skip(1) let call_method_name = Present { value: func_name } @@ -1475,9 +1988,6 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { // f: fn(T) -> ... so the lambda param binds to the concrete success // type. A single left-to-right fold infers each arg exactly once. let value_params = sig_params |> filter(p => !param_is_generic_decl(p: p, source_indices: scope.type_env.source_indices)) - let generic_names = sig_params - |> filter(p => param_is_generic_decl(p: p, source_indices: scope.type_env.source_indices)) - |> map(p => authored_name_at(source_indices: scope.type_env.source_indices, node: param_node_type_expr(n: p))) let final_state = fold(call_args |> enumerate, init: ArgGenericFoldState { results: [], subst: empty_map() }, f: (st, pair) => let a = pair.second let formal_lookup = value_params |> skip(pair.first) |> first @@ -1521,6 +2031,7 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { value_params: value_params_for_check, typed_args: typed_args, call_subst: call_subst, + generic_names: generic_names, type_env: scope.type_env, module_name: scope.module_name ) @@ -1560,7 +2071,8 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { source_indices: scope.type_env.source_indices ) let is_known_method = method_resolution.result_type != none - if is_known_method && typed_args |> count > 0 { + let is_builtin_function = infer_builtin_call_type(name: func_name) != none + if is_known_method && typed_args |> count > 0 && !is_builtin_function { let receiver = method_receiver let remaining = typed_args |> skip(1) let base_result_type = match method_resolution.result_type { @@ -1758,7 +2270,7 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { } } } - } else if infer_builtin_call_type(name: func_name) != none { + } else if is_builtin_function { let tier2b = infer_tier2b_builtin_with_kernel_diags(func_name: func_name, typed_args: typed_args, scope: scope, span: span) let bt = tier2b.bt let call_semantics = if func_name == "lookup" { @@ -1796,40 +2308,46 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { inferred: Present { value: Resolved { node: resolved_type } }, span: span, name_span: node_name_span(n: texpr) - ), - diagnostics: arg_diags - } - } else { - match infer_variant_constructor_call(func_name: func_name, call_args: call_args, span: span, name_span: node_name_span(n: texpr), scope: scope) { - Present { value: ctor_result } => ctor_result - Absent => - let type_match = lookup_type_by_name(env: scope.type_env, name: func_name) - let resolved_type = match type_match { - Present { value: tn } => tn - Absent => error_type - } - let call_diags = match type_match { - Present { value: _ } => [] - Absent => [inference_error( - message: concat("function '", func_name, "' not found in scope"), - span: span, - module_name: scope.module_name - )] - } - InferResult { - typed: make_named_expr_node( - name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, - children: typed_arg_nodes, - inferred: Present { value: Resolved { node: resolved_type } }, - span: span, - name_span: node_name_span(n: texpr) ), - diagnostics: concat(arg_diags, call_diags) + diagnostics: arg_diags + } + } else { + let collision = map_get(scope.variant_collisions, func_name) + if collision != none { + variant_collision_result(name: func_name, span: span, collision: collision.value) + } else { + let ctor = infer_variant_constructor_call(func_name: func_name, call_args: call_args, span: span, name_span: node_name_span(n: texpr), scope: scope) + if ctor != none { + ctor.value + } else { + let type_match = lookup_type_by_name(env: scope.type_env, name: func_name) + let resolved_type = match type_match { + Present { value: tn } => tn + Absent => error_type + } + let call_diags = match type_match { + Present { value: _ } => [] + Absent => [inference_error( + message: concat("function '", func_name, "' not found in scope"), + span: span, + module_name: scope.module_name + )] + } + InferResult { + typed: make_named_expr_node( + name: func_name, expr_data: ExprCall { call_semantics: Present { value: PlainCallSemantics }, descent_evidence: none }, + children: typed_arg_nodes, + inferred: Present { value: Resolved { node: resolved_type } }, + span: span, + name_span: node_name_span(n: texpr) + ), + diagnostics: concat(arg_diags, call_diags) + } } + } + } } } - } - } ExprMethodCall { method_semantics: _ } => let method_name = expr_method_name_at(texpr: texpr, source_indices: scope.type_env.source_indices) @@ -2056,10 +2574,25 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { let else_diags = else_result.diagnostics let then_rt = resolved_type(n: then_typed) let else_rt = resolved_type(n: else_typed) - let unified = prefer_specific_type(left: then_rt, right: else_rt, source_indices: scope.type_env.source_indices) + let then_is_none = direct_call_actual_is_none(actual_expr: then_expr, actual_type: then_rt, source_indices: scope.type_env.source_indices) + let else_is_none = direct_call_actual_is_none(actual_expr: else_branch, actual_type: else_rt, source_indices: scope.type_env.source_indices) + let then_compare_raw = direct_call_arg_decl_identity(n: then_rt, env: scope.type_env) + let else_compare_raw = direct_call_arg_decl_identity(n: else_rt, env: scope.type_env) + let then_compare_stamped = stamp_hidden_dependency_refs(n: then_compare_raw, dep_env: scope.type_env, source_indices: scope.type_env.source_indices) + let else_compare_stamped = stamp_hidden_dependency_refs(n: else_compare_raw, dep_env: scope.type_env, source_indices: scope.type_env.source_indices) + let then_compare = if else_is_none && !then_is_none { with_optional_cardinality(n: then_compare_stamped) } else { then_compare_stamped } + let else_compare = if then_is_none && !else_is_none { with_optional_cardinality(n: else_compare_stamped) } else { else_compare_stamped } + let unified_raw = prefer_specific_type(left: then_rt, right: else_rt, source_indices: scope.type_env.source_indices) + let unified = if then_is_none && !else_is_none { + with_optional_cardinality(n: else_rt) + } else if else_is_none && !then_is_none { + with_optional_cardinality(n: then_rt) + } else { + unified_raw + } let branch_diags = if node_type_compatible( - left: then_rt, - right: else_rt, + left: then_compare, + right: else_compare, source_indices: scope.type_env.source_indices ) { [] @@ -2127,7 +2660,7 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { ExprRecordLit { parent_enum: _ } => let span = texpr.span let field_inits = texpr.children - infer_record_lit(type_name: record_lit_type_name_at(texpr: texpr, source_indices: scope.type_env.source_indices), field_inits: field_inits, span: span, name_span: node_name_span(n: texpr), scope: scope) + infer_record_lit(type_name: record_lit_type_name_at(texpr: texpr, source_indices: scope.type_env.source_indices), field_inits: field_inits, span: span, name_span: node_name_span(n: texpr), scope: scope, expected: expected) ExprListLit => let span = texpr.span @@ -2135,7 +2668,15 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { let elem_expected = match expected { Present { value: exp } => if node_is_element_collection(n: exp, source_indices: scope.type_env.source_indices) { - match exp.children |> first { Present { value: elem } => Present { value: child_type_node(ch: elem) } Absent => none } + match exp.children |> first { + Present { value: elem } => + let child = child_type_node(ch: elem) + match lookup_type_for(env: scope.type_env, node: child) { + Present { value: resolved_child } => Present { value: resolved_child } + Absent => Present { value: child } + } + Absent => none + } } else { none } Absent => none } @@ -2143,9 +2684,13 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { let typed_elements = elem_results |> map(r => r.typed) let elem_diags = flat_map(elem_results, r => r.diagnostics) let elem_type_node = if count(elem_results) > 0 { - match first(elem_results) { - Present { value: r } => resolved_type(n: r.typed) - Absent => unit_type + match elem_expected { + Present { value: expected_elem } => expected_elem + Absent => + match first(elem_results) { + Present { value: r } => resolved_type(n: r.typed) + Absent => unit_type + } } } else { match expected { @@ -2255,12 +2800,13 @@ fn infer_expr(texpr: Node, scope: InferScope, expected: Node?) -> InferResult { Present { value: callable_inferred(n: exp) } } else { none } } else { none } - let body_scope = InferScope { - type_env: lam_scope.type_env, func_env: lam_scope.func_env, - locals: lam_scope.locals, match_bound_names: lam_scope.match_bound_names, - module_name: lam_scope.module_name, service_registry: lam_scope.service_registry, - item_registry: lam_scope.item_registry, lambda_param_provenance: empty_map() - } + let body_scope = InferScope { + type_env: lam_scope.type_env, func_env: lam_scope.func_env, + locals: lam_scope.locals, match_bound_names: lam_scope.match_bound_names, + variant_collisions: lam_scope.variant_collisions, + module_name: lam_scope.module_name, service_registry: lam_scope.service_registry, + item_registry: lam_scope.item_registry, lambda_param_provenance: empty_map() + } let body_result = infer_expr(texpr: lam_body, scope: body_scope, expected: body_expected) let body_typed = body_result.typed let body_diags = body_result.diagnostics @@ -2539,7 +3085,8 @@ fn infer_variant_constructor_call(func_name: String, call_args: List, span field_inits: [payload_init], span: span, name_span: name_span, - scope: scope + scope: scope, + expected: none ) } } Absent => none @@ -2563,8 +3110,8 @@ fn infer_variant_constructor_call(func_name: String, call_args: List, span } -fn infer_record_lit(type_name: String?, field_inits: List, span: SourceSpan, name_span: SourceSpan, scope: InferScope) -> InferResult { - let struct_fields = record_lit_expected_fields(type_name: type_name, scope: scope) +fn infer_record_lit(type_name: String?, field_inits: List, span: SourceSpan, name_span: SourceSpan, scope: InferScope, expected: Node?) -> InferResult { + let struct_fields = record_lit_expected_fields(type_name: type_name, scope: scope, expected: expected) let fi_infer_results = map(field_inits, fi => let fi_name = field_init_node_name_at(n: fi, source_indices: scope.type_env.source_indices) let field_expected = match struct_fields |> filter(sf => authored_name_at(source_indices: scope.type_env.source_indices, node: sf) == fi_name) |> first { @@ -2579,19 +3126,43 @@ fn infer_record_lit(type_name: String?, field_inits: List, span: SourceSpa let field_type_diags = match field_expected { Present { value: expected_node } => let got_node = resolved_type(n: ar_typed) - if rejects_string_for_optional_coproduct_field( + let expected_decl = lookup_type_for(env: scope.type_env, node: expected_node) + let expected_diag_node = match expected_decl { + Present { value: decl_node } => decl_node + Absent => expected_node + } + let string_optional_reject = rejects_string_for_optional_coproduct_field( expected: expected_node, got: got_node, source_indices: scope.type_env.source_indices - ) { + ) + let got_is_string = got_node.name == "String" + let named_optional_coproduct_string_reject = match expected_node.return_cardinality { + CardOptional => + match got_is_string { + true => expected_diag_node.connective == Disj + false => false + } + _ => false + } + if string_optional_reject { [type_mismatch_error( - expected: node_type_shape(n: expected_node, source_indices: scope.type_env.source_indices), + expected: node_type_shape(n: expected_diag_node, source_indices: scope.type_env.source_indices), got: node_type_shape(n: got_node, source_indices: scope.type_env.source_indices), span: ar_typed.span, module_name: scope.module_name )] } else { - [] + if named_optional_coproduct_string_reject { + [type_mismatch_error( + expected: node_type_shape(n: expected_diag_node, source_indices: scope.type_env.source_indices), + got: node_type_shape(n: got_node, source_indices: scope.type_env.source_indices), + span: ar_typed.span, + module_name: scope.module_name + )] + } else { + [] + } } Absent => [] } @@ -2603,8 +3174,22 @@ fn infer_record_lit(type_name: String?, field_inits: List, span: SourceSpa ) let typed_fields = fi_infer_results |> map(fir => fir.typed_field) let fi_diags = flat_map(fi_infer_results, fir => fir.diagnostics) - if type_name == none { - let child_nodes = fi_infer_results |> map(fir => + if type_name != none && map_get(scope.variant_collisions, type_name.value) != none { + let collision = map_get(scope.variant_collisions, type_name.value).value + let texpr = make_named_expr_node( + name: type_name.value, + expr_data: ExprRecordLit { parent_enum: none }, + children: typed_fields, + inferred: Present { value: Resolved { node: error_type } }, + span: span, + name_span: name_span + ) + InferResult { + typed: texpr, + diagnostics: concat(fi_diags, [collision]) + } + } else if type_name == none { + let child_nodes = fi_infer_results |> map(fir => Node { name: field_init_node_name_at(n: fir.typed_field, source_indices: scope.type_env.source_indices), span: fir.typed_field.span, ident_span: fir.typed_field.ident_span, children: [], connective: NoConnective, @@ -2627,23 +3212,55 @@ fn infer_record_lit(type_name: String?, field_inits: List, span: SourceSpa } else { let type_lookup = lookup_type_by_name(env: scope.type_env, name: type_name.value) let local_variant_parent = lookup_variant_parent_enum(scope: scope, name: type_name.value) + let expected_variant_parent = match expected { + Present { value: expected_node } => + match expected_coproduct_variant(parent: expected_node, variant_name: type_name.value, source_indices: scope.type_env.source_indices) { + Present { value: _ } => Present { value: authored_name_at(source_indices: scope.type_env.source_indices, node: expected_node) } + Absent => none + } + Absent => none + } + let env_variant_parent = match lookup_coproduct_parent_binding_by_variant(env: scope.type_env, variant_name: type_name.value) { + Present { value: parent_binding } => Present { value: parent_binding.name } + Absent => none + } + let effective_variant_parent = match local_variant_parent { + Present { value: _ } => local_variant_parent + Absent => + match env_variant_parent { + Present { value: _ } => env_variant_parent + Absent => expected_variant_parent + } + } let effective_lookup = match type_lookup { Present { value: _ } => type_lookup Absent => let local_lookup = lookup_in_scope(locals: scope.locals, name: type_name.value) - match local_lookup { - Present { value: local_node } => - lookup_type_for(env: scope.type_env, node: local_node) - Absent => Absent - } - } + match local_lookup { + Present { value: local_node } => + lookup_type_for(env: scope.type_env, node: local_node) + Absent => + match lookup_coproduct_parent_binding_by_variant(env: scope.type_env, variant_name: type_name.value) { + Present { value: parent_binding } => Present { value: parent_binding.resolved } + Absent => + match expected { + Present { value: expected_node } => + match expected_coproduct_variant(parent: expected_node, variant_name: type_name.value, source_indices: scope.type_env.source_indices) { + Present { value: _ } => Present { value: expected_node } + Absent => none + } + Absent => none + } + } + } + } let raw_resolved = match effective_lookup { Present { value: tn } => tn Absent => error_type } - let expected_optional_parent = Present { value: "Optional" } - let is_present_ctor = type_name.value == "Present" && local_variant_parent == expected_optional_parent - let resolved_node = if is_present_ctor { + let expected_optional_parent = Present { value: "Optional" } + let is_present_ctor = type_name.value == "Present" && effective_variant_parent == expected_optional_parent + let resolved_node = if is_present_ctor { let val_field = fi_infer_results |> filter(fir => field_init_node_name_at(n: fir.typed_field, source_indices: scope.type_env.source_indices) == "value") |> first match val_field { Present { value: val_fir } => with_optional_cardinality(n: resolved_type(n: val_fir.infer_result.typed)) @@ -2662,7 +3279,7 @@ fn infer_record_lit(type_name: String?, field_inits: List, span: SourceSpa let rl_name = match type_name { Present { value: tn_val } => tn_val Absent => "" } let texpr = make_named_expr_node( name: rl_name, - expr_data: ExprRecordLit { parent_enum: local_variant_parent }, + expr_data: ExprRecordLit { parent_enum: effective_variant_parent }, children: typed_field_nodes2, inferred: Present { value: Resolved { node: resolved_node } }, span: span, @@ -5093,7 +5710,8 @@ fn substitute_generics(n: Node, subst: Map, source_indices: Map map(c => substitute_generics(n: c, subst: subst, source_indices: source_indices)), connective: n.connective, params: n.params |> map(p => substitute_generics(n: p, subst: subst, source_indices: source_indices)), @@ -5127,11 +5745,410 @@ fn collect_parent_bindings_filtered(envs: List) -> Map) -> Map { + fold(envs, init: empty_map(), f: (acc, env) => + let with_existing = map_merge(acc, env.carrier_bindings) + fold(env.bindings |> map_values, init: with_existing, f: (bacc, binding) => + match binding.resolved.binding_id { + Present { value: binding_id } => map_insert(bacc, binding_id, binding) + Absent => bacc + } + ) + ) +} + +fn lookup_type_binding_by_name_in_env(env: TypeEnv, name: String) -> TypeBinding? { + match env.bindings |> map_values |> filter(binding => binding.name == name) |> first { + Present { value: binding } => Present { value: binding } + Absent => + match env.carrier_bindings |> map_values |> filter(binding => binding.name == name) |> first { + Present { value: binding } => Present { value: binding } + Absent => none + } + } +} + +fn lookup_coproduct_parent_binding_by_variant(env: TypeEnv, variant_name: String) -> TypeBinding? { + let visible_matches = env.bindings |> map_values |> filter(binding => + binding.resolved.connective == Disj + && has_child_named(n: binding.resolved, name: variant_name, source_indices: env.source_indices) + ) + let carrier_matches = env.carrier_bindings |> map_values |> filter(binding => + binding.resolved.connective == Disj + && has_child_named(n: binding.resolved, name: variant_name, source_indices: env.source_indices) + ) + let matches = concat(visible_matches, carrier_matches) + if matches |> count == 1 { + matches |> first + } else { + none + } +} + +fn stamp_hidden_dependency_refs(n: Node, dep_env: TypeEnv, source_indices: Map) -> Node { + let stamped_children = n.children |> map(child => stamp_hidden_dependency_refs(n: child, dep_env: dep_env, source_indices: source_indices)) + let stamped_params = n.params |> map(param => stamp_hidden_dependency_refs(n: param, dep_env: dep_env, source_indices: source_indices)) + let stamped_inferred = match n.inferred { + Present { value: Resolved { node: rt } } => Present { value: Resolved { node: stamp_hidden_dependency_refs(n: rt, dep_env: dep_env, source_indices: source_indices) } } + _ => n.inferred + } + let rebuilt = Node { + name: n.name, ident: n.ident, binding_id: n.binding_id, + span: n.span, ident_span: n.ident_span, + children: stamped_children, connective: n.connective, + params: stamped_params, inferred: stamped_inferred, + return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, + properties: n.properties, type_annotation: n.type_annotation, + is_self_recursive: n.is_self_recursive, has_non_tail_self_call: n.has_non_tail_self_call, + match_pattern: n.match_pattern, expr_data: n.expr_data + } + let name = authored_name_at(source_indices: source_indices, node: rebuilt) + let bare_unbranded_ref = rebuilt.binding_id == none + && rebuilt.connective == NoConnective + && rebuilt.children |> count == 0 + && rebuilt.params |> count == 0 + && name != "" + if bare_unbranded_ref { + match lookup_type_binding_by_name_in_env(env: dep_env, name: name) { + Present { value: binding } => + if binding.resolved.binding_id != none { + node_with_preserved_binding_id(identity: binding.resolved, structural: rebuilt) + } else { rebuilt } + Absent => rebuilt + } + } else { rebuilt } +} + +fn stamp_type_binding_dependency_refs(binding: TypeBinding, dep_env: TypeEnv, source_indices: Map) -> TypeBinding { + TypeBinding { + name: binding.name, + resolved: stamp_hidden_dependency_refs(n: binding.resolved, dep_env: dep_env, source_indices: source_indices), + provenance: binding.provenance + } +} + +type CarrierClosureState { + carrier_bindings: Map + seen_names: Map + seen_binding_ids: Map +} + +type CarrierClosureDepsContext { + n: Node + dep_env: TypeEnv + source_indices: Map +} + +fn lookup_decl_type_binding_by_name_excluding_binding_id(env: TypeEnv, name: String, excluded_binding_id: BindingId) -> TypeBinding? { + fold(env.decl_registry |> map_values, init: none, f: (acc, decl) => + match acc { + Present { value: _ } => acc + Absent => + if decl.name == name && decl.binding_id != excluded_binding_id { + match map_get(env.bindings, decl.binding_key) { + Present { value: binding } => + if node_has_binding_id(n: binding.resolved, binding_id: decl.binding_id) { + Present { value: binding } + } else { + map_get(env.carrier_bindings, decl.binding_id) + } + Absent => map_get(env.carrier_bindings, decl.binding_id) + } + } else { none } + } + ) +} + +fn carrier_authority_target(binding: TypeBinding, dep_env: TypeEnv, target_name: String, fallback: Node) -> Node { + match binding.resolved.binding_id { + Present { value: alias_binding_id } => + match lookup_decl_type_binding_by_name_excluding_binding_id(env: dep_env, name: target_name, excluded_binding_id: alias_binding_id) { + Present { value: target_binding } => target_binding.resolved + Absent => fallback + } + Absent => fallback + } +} + +fn carrier_authority_binding(binding: TypeBinding, dep_env: TypeEnv, source_indices: Map) -> TypeBinding { + let resolved = binding.resolved + if resolved.connective == NoConnective && resolved.children |> count == 0 && resolved.params |> count == 0 { + match resolved.inferred { + Present { value: Resolved { node: target } } => + let declared_or_structural_target = target.binding_id != none || target.connective != NoConnective + if declared_or_structural_target { + let target_name = authored_name_at(source_indices: source_indices, node: target) + let target_authority = match lookup_type_by_name(env: dep_env, name: target_name) { + Present { value: resolved_target } => resolved_target + Absent => target + } + TypeBinding { name: binding.name, resolved: carrier_authority_target(binding: binding, dep_env: dep_env, target_name: target_name, fallback: target_authority), provenance: binding.provenance } + } else { binding } + _ => binding + } + } else { + let carrier_is_structural_shell = resolved.connective != NoConnective + || resolved.children |> count > 0 + || resolved.params |> count > 0 + let carrier_name = authored_name_at(source_indices: source_indices, node: resolved) + if carrier_is_structural_shell && carrier_name != "" && binding.name != carrier_name { + TypeBinding { name: binding.name, resolved: carrier_authority_target(binding: binding, dep_env: dep_env, target_name: carrier_name, fallback: resolved), provenance: binding.provenance } + } else { binding } + } +} + +fn type_binding_decl_binding_id(env: TypeEnv, binding: TypeBinding) -> BindingId? { + match binding.resolved.binding_id { + Present { value: binding_id } => + match map_get(env.decl_registry, binding_id) { + Present { value: decl } => + if decl.name == binding.name { Present { value: binding_id } } else { none } + Absent => none + } + Absent => + fold(env.decl_registry |> map_values, init: none, f: (acc, decl) => + match acc { + Present { value: _ } => acc + Absent => + if decl.name == binding.name { Present { value: decl.binding_id } } + else { none } + } + ) + } +} + +fn carrier_closure_direct_type_deps(n: Node, dep_env: TypeEnv, source_indices: Map) -> List { + let n_name = authored_name_at(source_indices: source_indices, node: n) + let authored_ref = if n.ident_span != none && n_name != "" && is_kernel_type(name: n_name) == false { + [n_name] + } else { [] } + let decl_ref = match n.binding_id { + Present { value: binding_id } => + match map_get(dep_env.decl_registry, binding_id) { + Present { value: decl } => + if decl.name != "" && decl.name != n_name && is_kernel_type(name: decl.name) == false { + [decl.name] + } else { [] } + Absent => [] + } + Absent => [] + } + concat(concat(authored_ref, decl_ref), node_type_deps(n: n, source_indices: source_indices)) +} + +fn carrier_closure_field_node_type_deps(child: Node, dep_env: TypeEnv, source_indices: Map) -> List { + carrier_closure_node_type_deps(n: field_node_type_expr(n: child), dep_env: dep_env, source_indices: source_indices) +} + +fn carrier_closure_node_conj_child_deps(ctx: CarrierClosureDepsContext) -> List { + let children = ctx.n.children + children |> flat_map(child => + carrier_closure_field_node_type_deps(child: child, dep_env: ctx.dep_env, source_indices: ctx.source_indices) + ) +} + +fn carrier_closure_node_plain_child_deps(ctx: CarrierClosureDepsContext) -> List { + let children = ctx.n.children + children |> flat_map(child => + carrier_closure_node_type_deps(n: child, dep_env: ctx.dep_env, source_indices: ctx.source_indices) + ) +} + +fn carrier_closure_node_type_deps(n: Node, dep_env: TypeEnv, source_indices: Map) -> List { + let base = carrier_closure_direct_type_deps(n: n, dep_env: dep_env, source_indices: source_indices) + let ctx = CarrierClosureDepsContext { n: n, dep_env: dep_env, source_indices: source_indices } + let conj_deps = carrier_closure_node_conj_child_deps(ctx: ctx) + let plain_deps = carrier_closure_node_plain_child_deps(ctx: ctx) + let child_deps = match n.connective { + Conj => conj_deps + _ => plain_deps + } + concat(base, child_deps) +} + +fn add_type_binding_dependency_closure(state: CarrierClosureState, binding: TypeBinding, dep_env: TypeEnv, source_indices: Map) -> CarrierClosureState { + let already_seen = match binding.resolved.binding_id { + Present { value: binding_id } => map_contains_key(state.seen_binding_ids, binding_id) + Absent => map_contains_key(state.seen_names, binding.name) + } + if already_seen { + state + } else { + let stamped = stamp_type_binding_dependency_refs(binding: binding, dep_env: dep_env, source_indices: source_indices) + let with_binding = match stamped.resolved.binding_id { + Present { value: binding_id } => + CarrierClosureState { + carrier_bindings: map_insert(state.carrier_bindings, binding_id, carrier_authority_binding(binding: stamped, dep_env: dep_env, source_indices: source_indices)), + seen_names: map_insert(state.seen_names, stamped.name, true), + seen_binding_ids: map_insert(state.seen_binding_ids, binding_id, true) + } + Absent => + CarrierClosureState { + carrier_bindings: state.carrier_bindings, + seen_names: map_insert(state.seen_names, stamped.name, true), + seen_binding_ids: state.seen_binding_ids + } + } + let with_decl_binding = match type_binding_decl_binding_id(env: dep_env, binding: binding) { + Present { value: decl_binding_id } => + CarrierClosureState { + carrier_bindings: map_insert(with_binding.carrier_bindings, decl_binding_id, carrier_authority_binding(binding: stamped, dep_env: dep_env, source_indices: source_indices)), + seen_names: with_binding.seen_names, + seen_binding_ids: map_insert(with_binding.seen_binding_ids, decl_binding_id, true) + } + Absent => with_binding + } + let deps = concat( + carrier_closure_node_type_deps(n: binding.resolved, dep_env: dep_env, source_indices: source_indices), + carrier_closure_node_type_deps(n: stamped.resolved, dep_env: dep_env, source_indices: source_indices) + ) + fold(deps, init: with_decl_binding, f: (acc, dep_name) => + match lookup_type_binding_by_name_in_env(env: dep_env, name: dep_name) { + Present { value: dep_binding } => add_type_binding_dependency_closure(state: acc, binding: dep_binding, dep_env: dep_env, source_indices: source_indices) + Absent => acc + } + ) + } +} + +fn add_node_dependency_closure(state: CarrierClosureState, n: Node, dep_env: TypeEnv, source_indices: Map) -> CarrierClosureState { + let stamped = stamp_hidden_dependency_refs(n: n, dep_env: dep_env, source_indices: source_indices) + let name = authored_name_at(source_indices: source_indices, node: stamped) + let with_self = if name != "" { + match lookup_type_binding_by_name_in_env(env: dep_env, name: name) { + Present { value: self_binding } => add_type_binding_dependency_closure(state: state, binding: self_binding, dep_env: dep_env, source_indices: source_indices) + Absent => state + } + } else { state } + let deps = concat( + carrier_closure_node_type_deps(n: n, dep_env: dep_env, source_indices: source_indices), + carrier_closure_node_type_deps(n: stamped, dep_env: dep_env, source_indices: source_indices) + ) + fold(deps, init: with_self, f: (acc, dep_name) => + match lookup_type_binding_by_name_in_env(env: dep_env, name: dep_name) { + Present { value: dep_binding } => add_type_binding_dependency_closure(state: acc, binding: dep_binding, dep_env: dep_env, source_indices: source_indices) + Absent => acc + } + ) +} + +fn carrier_closure_with_decl_rows(state: CarrierClosureState, env: TypeEnv) -> CarrierClosureState { + fold(env.decl_registry |> map_values, init: state, f: (acc, decl) => + if map_contains_key(acc.seen_names, decl.name) && !map_contains_key(acc.carrier_bindings, decl.binding_id) { + let binding_for_decl = match map_get(env.bindings, decl.binding_key) { + Present { value: binding } => Present { value: binding } + Absent => env.bindings |> map_values |> filter(binding => binding.name == decl.name) |> first + } + match binding_for_decl { + Present { value: binding } => + CarrierClosureState { + carrier_bindings: map_insert(acc.carrier_bindings, decl.binding_id, carrier_authority_binding(binding: binding, dep_env: env, source_indices: env.source_indices)), + seen_names: acc.seen_names, + seen_binding_ids: map_insert(acc.seen_binding_ids, decl.binding_id, true) + } + Absent => acc + } + } else { acc } + ) +} + +fn collect_import_carrier_bindings_for_import(acc: Map, imp: ResolvedImport, env: TypeEnv) -> Map { + let closure_state = fold(env.bindings |> map_values, init: CarrierClosureState { carrier_bindings: acc, seen_names: empty_map(), seen_binding_ids: empty_map() }, f: (state, binding) => + if imp.module_path == "std.types" && is_type_variable_name(name: binding.name) { + state + } else if import_allows_type_binding(imp: imp, binding: binding, env: env) { + add_type_binding_dependency_closure(state: state, binding: binding, dep_env: env, source_indices: env.source_indices) + } else { + state + } + ) + carrier_closure_with_decl_rows(state: closure_state, env: env).carrier_bindings +} + +fn collect_import_carrier_bindings_for_imported_funcs(acc: Map, imp: ResolvedImport, typed_parent: TypedModule) -> Map { + let env = typed_parent.type_env + let closure_state = fold(typed_parent.func_env.signatures |> map_values, init: CarrierClosureState { carrier_bindings: acc, seen_names: empty_map(), seen_binding_ids: empty_map() }, f: (state, sig) => + if import_allows_binding_name(imp: imp, name: sig.name) { + let with_return = add_node_dependency_closure(state: state, n: sig.inferred, dep_env: env, source_indices: env.source_indices) + fold(sig.params, init: with_return, f: (pacc, param) => + add_node_dependency_closure(state: pacc, n: param_node_type_expr(n: param), dep_env: env, source_indices: env.source_indices) + ) + } else { + state + } + ) + carrier_closure_with_decl_rows(state: closure_state, env: env).carrier_bindings +} + +fn import_allows_binding_name(imp: ResolvedImport, name: String) -> Bool { + imp.is_all || (imp.specific_names |> count == 0) || (imp.specific_names |> any(n => n == name)) +} + +fn import_allows_type_binding(imp: ResolvedImport, binding: TypeBinding, env: TypeEnv) -> Bool { + if import_allows_binding_name(imp: imp, name: binding.name) { + true + } else { + let allowed_child = binding.resolved.children |> any(child => + let child_name = authored_name_at(source_indices: env.source_indices, node: child) + imp.specific_names |> any(n => n == child_name) + ) + binding.resolved.connective == Disj && allowed_child + } +} + +fn collect_import_bindings_for_import(acc: Map, imp: ResolvedImport, env: TypeEnv) -> Map { + fold(map_keys(env.bindings), init: acc, f: (bacc, ident) => + let name = intern_str(table: env.intern_table, id: ident) + match map_get(env.bindings, ident) { + Present { value: binding } => + if imp.module_path == "std.types" && is_type_variable_name(name: name) { + bacc + } else if import_allows_type_binding(imp: imp, binding: binding, env: env) { + map_insert(bacc, ident, stamp_type_binding_dependency_refs(binding: binding, dep_env: env, source_indices: env.source_indices)) + } else { + bacc + } + Absent => bacc + } + ) +} + +type TypeDeclRegistrationAccum { + bindings: Map + decl_registry: Map + allocator: BindingIdAllocator +} + +fn register_type_decl_binding( + acc: TypeDeclRegistrationAccum, + item_ident: Int, + name: String, + module_name: String, + decl_span: SourceSpan, + resolved: Node, + provenance: SubValueRelation +) -> TypeDeclRegistrationAccum { + let binding_alloc = alloc_binding_id(allocator: acc.allocator) + let stamped = node_with_binding_id(n: resolved, binding_id: binding_alloc.binding_id) + TypeDeclRegistrationAccum { + bindings: map_insert(acc.bindings, item_ident, TypeBinding { name: name, resolved: stamped, provenance: provenance }), + decl_registry: map_insert(acc.decl_registry, binding_alloc.binding_id, TypeDeclBinding { + binding_id: binding_alloc.binding_id, + authority: TypeDeclAuthority { module_name: module_name, decl_name: name, decl_span: decl_span }, + binding_key: item_ident, + decl_arity: resolved.params |> count, + name: name, + provenance: provenance + }), + allocator: binding_alloc.allocator + } +} + fn kernel_span(name: String) -> SourceSpan { SourceSpan { file: concat(""), start: 0, end: string_length(s: name) } } -fn build_type_env(module: ResolvedModule, parent_index: Map, source_indices: Map, intern_table: InternTable) -> BuildTypeEnvResult { +fn build_type_env(module: ResolvedModule, parent_index: Map, source_indices: Map, intern_table: InternTable, allocator: BindingIdAllocator) -> BuildTypeEnvResult { let source_indices = fold(map_keys(kernel_type_set), init: source_indices, f: (acc, name) => map_insert(acc, concat(""), build_newline_index(file: concat(""), source: name)) ) @@ -5167,7 +6184,7 @@ fn build_type_env(module: ResolvedModule, parent_index: Map let node_fields = inductive_fields_list_to_map(fields: compiler_inductive_fields) let kernel_recursive_types = map_keys(compiler_recursive_types) |> map(name => intern(table: intern_table, s: name).id) let kernel_recursive_type_set = fold(map_keys(compiler_recursive_types), init: empty_map(), f: (acc, name) => map_insert(acc, intern(table: intern_table, s: name).id, true)) - let kernel = TypeEnv { bindings: kernel_bindings, recursive_types: kernel_recursive_types, recursive_type_set: kernel_recursive_type_set, inductive_fields: node_fields, source_indices: source_indices, intern_table: intern_table } + let kernel = TypeEnv { bindings: kernel_bindings, carrier_bindings: empty_map(), decl_registry: empty_map(), duplicate_decl_ids: [], recursive_types: kernel_recursive_types, recursive_type_set: kernel_recursive_type_set, inductive_fields: node_fields, source_indices: source_indices, intern_table: intern_table } let imports_std_types = module.resolved_imports |> any(imp => imp.module_path == "std.types") // Bootstrap bridge: seed std.types into modules that did not import it @@ -5186,33 +6203,38 @@ fn build_type_env(module: ResolvedModule, parent_index: Map // Filter algebra type variable names from std.types imports so they // do not leak as ambient user-facing type bindings. let std_import_bindings = collect_parent_bindings_filtered(envs: std_types_parent_env) - let import_bindings = fold(module.resolved_imports, init: std_import_bindings, f: (acc, imp) => - match map_get(parent_index, imp.module_path) { - Present { value: typed_parent } => - if imp.module_path == "std.types" { - fold(map_keys(typed_parent.type_env.bindings), init: acc, f: (bacc, ident) => - let name = intern_str(table: typed_parent.type_env.intern_table, id: ident) - if is_type_variable_name(name: name) { bacc } - else { - match map_get(typed_parent.type_env.bindings, ident) { - Present { value: binding } => map_insert(bacc, ident, binding) - Absent => bacc - } - } + let import_bindings = fold(module.resolved_imports, init: std_import_bindings, f: (acc, imp) => + match map_get(parent_index, imp.module_path) { + Present { value: typed_parent } => collect_import_bindings_for_import(acc: acc, imp: imp, env: typed_parent.type_env) + Absent => acc + } + ) + let std_import_carrier_bindings = collect_parent_carrier_bindings(envs: std_types_parent_env) + let import_carrier_bindings = fold(module.resolved_imports, init: std_import_carrier_bindings, f: (acc, imp) => + match map_get(parent_index, imp.module_path) { + Present { value: typed_parent } => + collect_import_carrier_bindings_for_imported_funcs( + acc: collect_import_carrier_bindings_for_import(acc: acc, imp: imp, env: typed_parent.type_env), + imp: imp, + typed_parent: typed_parent ) - } else { map_merge(acc, typed_parent.type_env.bindings) } - Absent => acc - } - ) + Absent => acc + } + ) let import_recursive = fold(parent_envs, init: [], f: (acc, env) => concat(acc, env.recursive_types)) + let import_decl_state = fold(parent_envs, init: TypeEnv { bindings: empty_map(), carrier_bindings: empty_map(), decl_registry: empty_map(), duplicate_decl_ids: [], recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: intern_table }, f: (acc, env) => + merge_envs(envs: [acc, TypeEnv { bindings: empty_map(), carrier_bindings: empty_map(), decl_registry: env.decl_registry, duplicate_decl_ids: env.duplicate_decl_ids, recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: intern_table }]) + ) let import_recursive_set = fold(parent_envs, init: empty_map(), f: (acc, env) => map_merge(acc, env.recursive_type_set)) let import_inductive_fields = fold(parent_envs, init: empty_map(), f: (acc, env) => merge_inductive_fields(left: acc, right: env.inductive_fields)) - let import_env = TypeEnv { bindings: import_bindings, recursive_types: import_recursive, recursive_type_set: import_recursive_set, inductive_fields: import_inductive_fields, source_indices: source_indices, intern_table: intern_table } - let import_diags = flat_map(module.resolved_imports, imp => match map_get(parent_index, imp.module_path) { Present { value: _ } => [] Absent => [make_error_node(diagnostic: InternalError { message: concat("missing parent environment for imported module '", imp.module_path, "' while typechecking '", module_name_str, "'"), span: imp.target_module.value.span }, module_name: module_name_str)] }) + let import_env = TypeEnv { bindings: import_bindings, carrier_bindings: import_carrier_bindings, decl_registry: import_decl_state.decl_registry, duplicate_decl_ids: import_decl_state.duplicate_decl_ids, recursive_types: import_recursive, recursive_type_set: import_recursive_set, inductive_fields: import_inductive_fields, source_indices: source_indices, intern_table: intern_table } + let import_diags = flat_map(module.resolved_imports, imp => match map_get(parent_index, imp.module_path) { Present { value: _ } => [] Absent => [make_error_node(diagnostic: InternalError { message: concat("missing parent environment for imported module '", imp.module_path, "' while typechecking '", module_name_str, "'"), span: imp.target_module.value.span }, module_name: module_name_str)] }) - let local_bindings = fold(module_items(n: module.module), init: empty_map(), f: (acc, item) => + let local_registration = fold(module_items(n: module.module), init: TypeDeclRegistrationAccum { bindings: empty_map(), decl_registry: empty_map(), allocator: allocator }, f: (acc, item) => let item_ident = intern(table: intern_table, s: authored_name_at(source_indices: source_indices, node: item)).id + let item_name = authored_name_at(source_indices: source_indices, node: item) let has_structure = item.connective != NoConnective + let params_are_generic_decls = item.params |> all(p => param_is_generic_decl(p: p, source_indices: source_indices)) if has_structure { let type_node = Node { name: item.name, span: item.span, ident_span: item.ident_span, children: item.children, @@ -5221,8 +6243,8 @@ fn build_type_env(module: ResolvedModule, parent_index: Map uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - map_insert(acc, item_ident, TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: type_node, provenance: SubValueUnknown }) - } else if item.inferred != none && item.params |> count == 0 && item.body == none { + register_type_decl_binding(acc: acc, item_ident: item_ident, name: item_name, module_name: module_name_str, decl_span: item.span, resolved: type_node, provenance: SubValueUnknown) + } else if item.inferred != none && item.body == none && (item.params |> count == 0 || params_are_generic_decls == false) { let alias_node = Node { name: item.name, span: item.span, ident_span: item.ident_span, children: [], connective: NoConnective, params: [], inferred: item.inferred, @@ -5230,11 +6252,11 @@ fn build_type_env(module: ResolvedModule, parent_index: Map uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - map_insert(acc, item_ident, TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: alias_node, provenance: SubValueUnknown }) + register_type_decl_binding(acc: acc, item_ident: item_ident, name: item_name, module_name: module_name_str, decl_span: item.span, resolved: alias_node, provenance: SubValueUnknown) } else if item.transport == none && item.children |> count > 0 { let ref_node = nominal_ref_node(name: authored_name_at(source_indices: source_indices, node: item), span: item.span, ident_span: item.ident_span) - map_insert(acc, item_ident, TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: ref_node, provenance: SubValueUnknown }) - } else if item.params |> count > 0 && item.connective == NoConnective && item.body == none && item.transport == none { + register_type_decl_binding(acc: acc, item_ident: item_ident, name: item_name, module_name: module_name_str, decl_span: item.span, resolved: ref_node, provenance: SubValueUnknown) + } else if item.params |> count > 0 && params_are_generic_decls && item.connective == NoConnective && item.body == none && item.transport == none { // Parameterized type declaration (e.g., type List = FreeMonoid). // Register as a nominal type with params so generics can find the declaration. // Preserve .inferred so alias chains (List → FreeMonoid) survive into the @@ -5246,13 +6268,16 @@ fn build_type_env(module: ResolvedModule, parent_index: Map uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - map_insert(acc, item_ident, TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: bare_node, provenance: SubValueUnknown }) + register_type_decl_binding(acc: acc, item_ident: item_ident, name: item_name, module_name: module_name_str, decl_span: item.span, resolved: bare_node, provenance: SubValueUnknown) } else if item.properties |> count > 0 && item.connective == NoConnective && item.transport == none && item.inferred == none && item.params |> count == 0 { - map_insert(acc, item_ident, nominal_type_binding(name: authored_name_at(source_indices: source_indices, node: item))) + register_type_decl_binding(acc: acc, item_ident: item_ident, name: item_name, module_name: module_name_str, decl_span: item.span, resolved: nominal_leaf_type(name: item_name), provenance: SubValueUnknown) } else { acc } ) + let local_bindings = local_registration.bindings + let local_decl_registry = local_registration.decl_registry + let allocator = local_registration.allocator // Register type parameter names from generic type declarations so inference // can resolve slot references (e.g., "A" and "B" in type Pair). // Slot names resolve to leaf nodes; normalization substitutes them at @@ -5270,7 +6295,7 @@ fn build_type_env(module: ResolvedModule, parent_index: Map ) let local_name_set = fold(local_bindings |> map_keys, init: empty_map(), f: (acc, ident) => map_insert(acc, ident, true)) let all_local_bindings = map_merge(local_bindings, param_bindings) - let pre_local_env = TypeEnv { bindings: all_local_bindings, recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: intern_table } + let pre_local_env = TypeEnv { bindings: all_local_bindings, carrier_bindings: empty_map(), decl_registry: local_decl_registry, duplicate_decl_ids: [], recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: intern_table } let merged = merge_envs(envs: [kernel, import_env, pre_local_env]) let all_deps_map = fold(merged.bindings |> map_values, init: empty_map(), f: (acc, b) => @@ -5288,12 +6313,16 @@ fn build_type_env(module: ResolvedModule, parent_index: Map let cross_type_set = fold(cross_type_all_names, init: empty_map(), f: (acc, name) => map_insert(acc, intern(table: intern_table, s: name).id, true)) let local_inductive_fields = build_item_inductive_fields(items: module_items(n: module.module), recursive_type_set: cross_type_set_str, source_indices: source_indices) let merged_inductive_fields = merge_inductive_fields(left: merged.inductive_fields, right: local_inductive_fields) - let unresolved_env = TypeEnv { bindings: merged.bindings, recursive_types: cycle_set, recursive_type_set: cross_type_set, inductive_fields: merged_inductive_fields, source_indices: source_indices, intern_table: intern_table } + let duplicate_decl_diags = merged.duplicate_decl_ids |> map(_ => make_error_node(diagnostic: InternalError { message: "duplicate BindingId in TypeEnv merge", span: module.module.span }, module_name: module_name_str)) + let unresolved_env = TypeEnv { bindings: merged.bindings, carrier_bindings: merged.carrier_bindings, decl_registry: merged.decl_registry, duplicate_decl_ids: merged.duplicate_decl_ids, recursive_types: cycle_set, recursive_type_set: cross_type_set, inductive_fields: merged_inductive_fields, source_indices: source_indices, intern_table: intern_table } let resolved = resolve_env_bindings(env: unresolved_env, module_name: module_name_str, local_names: local_name_set, deps_map: all_deps_map) let resolved_env_out = resolved.env let resolved_diags = resolved.diagnostics let final_env = TypeEnv { bindings: resolved_env_out.bindings, + carrier_bindings: resolved_env_out.carrier_bindings, + decl_registry: resolved_env_out.decl_registry, + duplicate_decl_ids: resolved_env_out.duplicate_decl_ids, recursive_types: resolved_env_out.recursive_types, recursive_type_set: resolved_env_out.recursive_type_set, inductive_fields: resolved_env_out.inductive_fields, @@ -5302,7 +6331,8 @@ fn build_type_env(module: ResolvedModule, parent_index: Map } BuildTypeEnvResult { env: final_env, - diagnostics: concat(import_diags, resolved_diags) + allocator: allocator, + diagnostics: concat(import_diags, duplicate_decl_diags, resolved_diags) } } @@ -5320,7 +6350,7 @@ fn build_type_env_unresolved(module: ResolvedModule, parent_index: Map any(imp => imp.module_path == "std.types") // Mirror the same bootstrap bridge in the unresolved path. let module_name_str = authored_name_at(source_indices: source_indices, node: module.module) @@ -5335,35 +6365,39 @@ fn build_type_env_unresolved(module: ResolvedModule, parent_index: Map match map_get(parent_index, imp.module_path) { Present { value: typed_parent } => [typed_parent.type_env] Absent => [] }) let parent_envs = concat(std_types_parent_env, imported_parent_envs) let std_import_bindings = collect_parent_bindings_filtered(envs: std_types_parent_env) - let import_bindings = fold(module.resolved_imports, init: std_import_bindings, f: (acc, imp) => - match map_get(parent_index, imp.module_path) { - Present { value: typed_parent } => - if imp.module_path == "std.types" { - fold(map_keys(typed_parent.type_env.bindings), init: acc, f: (bacc, ident) => - let name = intern_str(table: typed_parent.type_env.intern_table, id: ident) - if is_type_variable_name(name: name) { bacc } - else { - match map_get(typed_parent.type_env.bindings, ident) { - Present { value: binding } => map_insert(bacc, ident, binding) - Absent => bacc - } - } + let import_bindings = fold(module.resolved_imports, init: std_import_bindings, f: (acc, imp) => + match map_get(parent_index, imp.module_path) { + Present { value: typed_parent } => collect_import_bindings_for_import(acc: acc, imp: imp, env: typed_parent.type_env) + Absent => acc + } + ) + let std_import_carrier_bindings = collect_parent_carrier_bindings(envs: std_types_parent_env) + let import_carrier_bindings = fold(module.resolved_imports, init: std_import_carrier_bindings, f: (acc, imp) => + match map_get(parent_index, imp.module_path) { + Present { value: typed_parent } => + collect_import_carrier_bindings_for_imported_funcs( + acc: collect_import_carrier_bindings_for_import(acc: acc, imp: imp, env: typed_parent.type_env), + imp: imp, + typed_parent: typed_parent ) - } else { map_merge(acc, typed_parent.type_env.bindings) } - Absent => acc - } - ) + Absent => acc + } + ) let import_recursive = fold(parent_envs, init: [], f: (acc, env) => concat(acc, env.recursive_types)) + let import_decl_state = fold(parent_envs, init: TypeEnv { bindings: empty_map(), carrier_bindings: empty_map(), decl_registry: empty_map(), duplicate_decl_ids: [], recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: intern_table }, f: (acc, env) => + merge_envs(envs: [acc, TypeEnv { bindings: empty_map(), carrier_bindings: empty_map(), decl_registry: env.decl_registry, duplicate_decl_ids: env.duplicate_decl_ids, recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: intern_table }]) + ) let import_recursive_set = fold(parent_envs, init: empty_map(), f: (acc, env) => map_merge(acc, env.recursive_type_set)) let import_inductive_fields = fold(parent_envs, init: empty_map(), f: (acc, env) => merge_inductive_fields(left: acc, right: env.inductive_fields)) - let import_env = TypeEnv { bindings: import_bindings, recursive_types: import_recursive, recursive_type_set: import_recursive_set, inductive_fields: import_inductive_fields, source_indices: source_indices, intern_table: intern_table } + let import_env = TypeEnv { bindings: import_bindings, carrier_bindings: import_carrier_bindings, decl_registry: import_decl_state.decl_registry, duplicate_decl_ids: import_decl_state.duplicate_decl_ids, recursive_types: import_recursive, recursive_type_set: import_recursive_set, inductive_fields: import_inductive_fields, source_indices: source_indices, intern_table: intern_table } let local_bindings = fold(module_items(n: module.module), init: empty_map(), f: (acc, item) => let item_ident = intern(table: intern_table, s: authored_name_at(source_indices: source_indices, node: item)).id let has_structure = item.connective != NoConnective + let params_are_generic_decls = item.params |> all(p => param_is_generic_decl(p: p, source_indices: source_indices)) if has_structure { let type_node = Node { name: item.name, span: item.span, ident_span: item.ident_span, children: item.children, connective: item.connective, params: [], inferred: none, return_cardinality: item.return_cardinality, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } map_insert(acc, item_ident, TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: type_node, provenance: SubValueUnknown }) - } else if item.inferred != none && item.params |> count == 0 && item.body == none { + } else if item.inferred != none && item.body == none && (item.params |> count == 0 || params_are_generic_decls == false) { let alias_node = Node { name: item.name, span: item.span, ident_span: item.ident_span, children: [], connective: NoConnective, params: [], inferred: item.inferred, return_cardinality: item.return_cardinality, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } map_insert(acc, item_ident, TypeBinding { name: authored_name_at(source_indices: source_indices, node: item), resolved: alias_node, provenance: SubValueUnknown }) } else if item.transport == none && item.children |> count > 0 { @@ -5375,7 +6409,7 @@ fn build_type_env_unresolved(module: ResolvedModule, parent_index: Map map_values, init: empty_map(), f: (acc, b) => map_insert(acc, b.name, node_type_deps(n: b.resolved, source_indices: source_indices)) @@ -5391,8 +6425,8 @@ fn build_type_env_unresolved(module: ResolvedModule, parent_index: Map map_insert(acc, intern(table: intern_table, s: name).id, true)) let local_inductive_fields = build_item_inductive_fields(items: module_items(n: module.module), recursive_type_set: cross_type_set_str, source_indices: source_indices) let merged_inductive_fields = merge_inductive_fields(left: merged.inductive_fields, right: local_inductive_fields) - let unresolved_env = TypeEnv { bindings: merged.bindings, recursive_types: cycle_set, recursive_type_set: cross_type_set, inductive_fields: merged_inductive_fields, source_indices: source_indices, intern_table: intern_table } - BuildTypeEnvResult { env: unresolved_env, diagnostics: [] } + let unresolved_env = TypeEnv { bindings: merged.bindings, carrier_bindings: merged.carrier_bindings, decl_registry: merged.decl_registry, duplicate_decl_ids: merged.duplicate_decl_ids, recursive_types: cycle_set, recursive_type_set: cross_type_set, inductive_fields: merged_inductive_fields, source_indices: source_indices, intern_table: intern_table } + BuildTypeEnvResult { env: unresolved_env, allocator: empty_binding_id_allocator(), diagnostics: [] } } @@ -5540,39 +6574,89 @@ fn build_module_context(contributions: List, diag_chunks: [], source_indices: env.source_indices ) - let imported_enum_names = fold(resolved_imports, init: empty_map(), f: (acc, imp) => - fold(imp.specific_names, init: acc, f: (inner, n) => map_insert(inner, n, true)) - ) - let variant_fold = fold(env.bindings |> map_values, init: VariantFoldState { locals: empty_map(), collision_errors: [] }, f: (acc, binding) => - let is_coproduct = binding.resolved.connective == Disj - if is_coproduct { - let curr_is_imported = map_get(imported_enum_names, authored_name_at(source_indices: env.source_indices, node: binding.resolved)) != none - fold(binding.resolved.children, init: acc, f: (vacc, child) => - match map_get(vacc.locals, authored_name_at(source_indices: env.source_indices, node: child)) { - Present { value: prev } => - let prev_is_imported = map_get(imported_enum_names, authored_name_at(source_indices: env.source_indices, node: prev.resolved)) != none - if curr_is_imported && prev_is_imported { - VariantFoldState { - locals: vacc.locals, - collision_errors: list_push(vacc.collision_errors, make_error_node(diagnostic: VariantCollision { variant: authored_name_at(source_indices: env.source_indices, node: child), enum1: authored_name_at(source_indices: env.source_indices, node: prev.resolved), enum2: authored_name_at(source_indices: env.source_indices, node: binding.resolved), span: no_span() }, module_name: module_name)) - } - } else if curr_is_imported { - VariantFoldState { - locals: map_insert(vacc.locals, authored_name_at(source_indices: env.source_indices, node: child), TypeBinding { name: authored_name_at(source_indices: env.source_indices, node: child), resolved: binding.resolved, provenance: SubValueUnknown }), - collision_errors: vacc.collision_errors - } - } else { vacc } - Absent => - VariantFoldState { - locals: map_insert(vacc.locals, authored_name_at(source_indices: env.source_indices, node: child), TypeBinding { name: authored_name_at(source_indices: env.source_indices, node: child), resolved: binding.resolved, provenance: SubValueUnknown }), - collision_errors: vacc.collision_errors - } + let imported_enum_names = fold(resolved_imports, init: empty_map(), f: (acc, imp) => + match map_get(parent_index, imp.module_path) { + Present { value: typed_parent } => + fold(typed_parent.type_env.bindings |> map_values, init: acc, f: (inner, parent_binding) => + let parent_name = parent_binding.name + if parent_binding.resolved.connective == Disj && import_allows_binding_name(imp: imp, name: parent_name) { + map_insert(inner, parent_name, true) + } else { inner } + ) + Absent => acc } ) - } else { acc } - ) - let imported_variant_locals = variant_fold.locals - let variant_collision_errors = variant_fold.collision_errors + let imported_variant_parent_names = fold(resolved_imports, init: empty_map(), f: (acc, imp) => + match map_get(parent_index, imp.module_path) { + Present { value: typed_parent } => + fold(imp.specific_names, init: acc, f: (inner, n) => + fold(typed_parent.type_env.bindings |> map_values, init: inner, f: (pacc, parent_binding) => + let parent_name = parent_binding.name + if parent_binding.resolved.connective == Disj && import_allows_binding_name(imp: imp, name: parent_name) == false && has_child_named(n: parent_binding.resolved, name: n, source_indices: typed_parent.type_env.source_indices) { + map_insert(pacc, concat(parent_name, "::", n), true) + } else { pacc } + ) + ) + Absent => acc + } + ) + let variant_fold = fold(env.bindings |> map_values, init: VariantFoldState { locals: empty_map(), collisions: empty_map() }, f: (acc, binding) => + let is_coproduct = binding.resolved.connective == Disj + if is_coproduct { + let curr_parent_name = authored_name_at(source_indices: env.source_indices, node: binding.resolved) + let curr_parent_imported = curr_parent_name == "Optional" || map_get(imported_enum_names, curr_parent_name) != none + fold(binding.resolved.children, init: acc, f: (vacc, child) => + let child_name = authored_name_at(source_indices: env.source_indices, node: child) + let curr_variant_imported = map_get(imported_variant_parent_names, concat(curr_parent_name, "::", child_name)) != none + let curr_is_imported = curr_parent_imported || curr_variant_imported + match map_get(vacc.locals, child_name) { + Present { value: prev } => + let prev_parent_name = authored_name_at(source_indices: env.source_indices, node: prev.resolved) + let prev_parent_imported = map_get(imported_enum_names, prev_parent_name) != none + let prev_variant_imported = map_get(imported_variant_parent_names, concat(prev_parent_name, "::", child_name)) != none + let prev_is_imported = prev_parent_imported || prev_variant_imported + let same_parent_binding = match binding.resolved.binding_id { + Present { value: curr_binding_id } => + match prev.resolved.binding_id { + Present { value: prev_binding_id } => + curr_binding_id == prev_binding_id || + match map_get(env.decl_registry, curr_binding_id) { + Present { value: curr_decl } => + match map_get(env.decl_registry, prev_binding_id) { + Present { value: prev_decl } => curr_decl.authority == prev_decl.authority + Absent => false + } + Absent => false + } + Absent => false + } + Absent => curr_parent_name == prev_parent_name + } + let same_parent_binding = same_parent_binding || same_canonical_container_variant_parent(left: binding.resolved, right: prev.resolved, source_indices: env.source_indices) + if curr_variant_imported && prev_variant_imported && same_parent_binding == false && is_bootstrap_duplicate_variant_name(name: child_name) == false && curr_parent_imported == false && prev_parent_imported == false && curr_is_imported && prev_is_imported { + VariantFoldState { + locals: vacc.locals, + collisions: map_insert(vacc.collisions, child_name, make_error_node(diagnostic: VariantCollision { variant: child_name, enum1: prev_parent_name, enum2: curr_parent_name, span: no_span() }, module_name: module_name)) + } + } else if curr_parent_imported && prev_parent_imported == false { + VariantFoldState { + locals: map_insert(vacc.locals, child_name, TypeBinding { name: child_name, resolved: binding.resolved, provenance: SubValueUnknown }), + collisions: vacc.collisions + } + } else { vacc } + Absent => + if curr_is_imported { + VariantFoldState { + locals: map_insert(vacc.locals, child_name, TypeBinding { name: child_name, resolved: binding.resolved, provenance: SubValueUnknown }), + collisions: vacc.collisions + } + } else { vacc } + } + ) + } else { acc } + ) + let imported_variant_locals = variant_fold.locals + let variant_collisions = variant_fold.collisions let env_variant_locals = variant_locals_from_items(items: local.resolved_items, init: imported_variant_locals, source_indices: env.source_indices) let merged_scope = merge_scope_from_imports( remaining: resolved_imports, @@ -5595,12 +6679,13 @@ fn build_module_context(contributions: List, ModuleContext { resolved_items: local.resolved_items, func_env: resolve_result.func_env, - svc_registry: merged_scope.svc_registry, - locals: all_locals, - item_registry: local.item_registry, - diagnostics: concat(concat(flat_map(local.diag_chunks, c => c), resolve_result.diagnostics), variant_collision_errors) + svc_registry: merged_scope.svc_registry, + locals: all_locals, + item_registry: local.item_registry, + variant_collisions: variant_collisions, + diagnostics: concat(flat_map(local.diag_chunks, c => c), resolve_result.diagnostics) + } } -} // ========================================================================= // Typecheck a single module @@ -5608,13 +6693,15 @@ fn build_module_context(contributions: List, type TypecheckModuleResult { typed: TypedModule + allocator: BindingIdAllocator diagnostics: List } -fn typecheck_module(resolved: ResolvedModule, parent_index: Map, source_indices: Map, intern_table: InternTable) -> TypecheckModuleResult { - let env_result = build_type_env(module: resolved, parent_index: parent_index, source_indices: source_indices, intern_table: intern_table) +fn typecheck_module(resolved: ResolvedModule, parent_index: Map, source_indices: Map, intern_table: InternTable, allocator: BindingIdAllocator) -> TypecheckModuleResult { + let env_result = build_type_env(module: resolved, parent_index: parent_index, source_indices: source_indices, intern_table: intern_table, allocator: allocator) let env = env_result.env + let allocator = env_result.allocator let env_diags = env_result.diagnostics // Gate: if type environment construction produced errors (unresolved types), @@ -5631,6 +6718,7 @@ fn typecheck_module(resolved: ResolvedModule, parent_index: Map if item.is_self_recursive && item.body != none { Node { - name: item.name, span: item.span, ident_span: item.ident_span, + name: item.name, ident: item.ident, binding_id: item.binding_id, + span: item.span, ident_span: item.ident_span, children: item.children, params: item.params, inferred: item.inferred, return_cardinality: item.return_cardinality, uses: item.uses, @@ -5702,6 +6792,7 @@ fn typecheck_module(resolved: ResolvedModule, parent_index: Map, inte item_registry: empty_map(), diag_chunks: [], source_indices: source_indices, - intern_table: intern_table + intern_table: intern_table, + allocator: empty_binding_id_allocator() ) } @@ -5957,7 +7049,8 @@ fn typecheck_modules( item_registry: Map, diag_chunks: List>, source_indices: Map, - intern_table: InternTable + intern_table: InternTable, + allocator: BindingIdAllocator ) -> TypedGraph { match remaining |> first { Absent => @@ -5965,9 +7058,10 @@ fn typecheck_modules( TypedGraph { modules: modules, item_registry: expanded_registry, diagnostics: flat_map(diag_chunks, c => c) } Present { value: resolved } => let parent_result = collect_parent_envs(resolved: resolved, module_index: module_index, source_indices: source_indices) - let tc_result = typecheck_module(resolved: resolved, parent_index: module_index, source_indices: source_indices, intern_table: intern_table) + let tc_result = typecheck_module(resolved: resolved, parent_index: module_index, source_indices: source_indices, intern_table: intern_table, allocator: allocator) let typed = tc_result.typed let tc_diags = tc_result.diagnostics + let allocator = tc_result.allocator typecheck_modules( remaining: remaining |> skip(1), modules: list_push(modules, typed), @@ -5975,7 +7069,8 @@ fn typecheck_modules( item_registry: map_merge(item_registry, typed.item_registry), diag_chunks: list_push(list_push(diag_chunks, parent_result.diagnostics), tc_diags), source_indices: source_indices, - intern_table: intern_table + intern_table: intern_table, + allocator: allocator ) } } diff --git a/src/v2/04_lookup.dag b/src/v2/04_lookup.dag index 753edefbeec..55d6b155b67 100644 --- a/src/v2/04_lookup.dag +++ b/src/v2/04_lookup.dag @@ -184,7 +184,8 @@ fn resolve_scrutinee_type_node_seen(env: TypeEnv, n: Node, seen: Map normed + Absent => + normed } } } else { normed } diff --git a/src/v2/04_resolve.dag b/src/v2/04_resolve.dag index 63b22a2c21f..1205e100eef 100644 --- a/src/v2/04_resolve.dag +++ b/src/v2/04_resolve.dag @@ -31,14 +31,14 @@ import v2.std.core { Connective, Conj, Disj, NoConnective, CardOptional, no_span, unit_type, string_type, - default_ident_span, kernel_span, node_name_span, intern + default_ident_span, kernel_span, node_name_span, node_with_preserved_binding_id, intern } import v2.compiler.infer_types { - resolved_type, child_type_node, node_is_keyed_collection, is_declared_container_alias_spelling + resolved_type, child_type_node, node_is_keyed_collection, is_declared_container_alias_spelling, node_is_bare_type_ref } import std.induction { SubValueUnknown } import v2.compiler.infer_env { - TypeEnv, TypeBinding, lookup_type, lookup_type_by_name, lookup_type_for, is_recursive_type, is_recursive_type_by_name, is_recursive_type_for, authored_name + TypeEnv, TypeBinding, lookup_type, lookup_type_by_name, lookup_type_for, lookup_decl_arity_for, is_recursive_type, is_recursive_type_by_name, is_recursive_type_for, authored_name } fn is_type_variable(inferred: InferredNode) -> Bool { @@ -48,19 +48,10 @@ fn is_type_variable(inferred: InferredNode) -> Bool { } } -// When peeling a one-level type alias to its structural target, keep the -// declaration/reference ident_span so authored_name_at still reports the brand -// name (UserId vs AccountId) instead of the shared carrier (Refined). -fn with_authored_identity(identity: Node, structural: Node) -> Node { - Node { - name: structural.name, ident: structural.ident, span: structural.span, ident_span: identity.ident_span, - children: structural.children, connective: structural.connective, params: structural.params, - inferred: structural.inferred, return_cardinality: structural.return_cardinality, - uses: structural.uses, body: structural.body, transport: structural.transport, - properties: structural.properties, type_annotation: structural.type_annotation, - is_self_recursive: structural.is_self_recursive, has_non_tail_self_call: structural.has_non_tail_self_call, - match_pattern: structural.match_pattern, expr_data: structural.expr_data - } +// When peeling a one-level type alias to its structural target, carry +// declaration identity on binding_id while leaving ident_span as source span. +fn with_preserved_binding_id(identity: Node, structural: Node) -> Node { + node_with_preserved_binding_id(identity: identity, structural: structural) } // After env binding resolve, keep declaration-site brand on the structural carrier. @@ -70,43 +61,66 @@ fn preserve_nominal_brand_on_resolve( brand_name: String, source_indices: Map ) -> Node { - if brand_name != "" && brand_name != authored_name_at(source_indices: source_indices, node: structural) + if identity.binding_id != none && brand_name != "" && !is_declared_container_alias_spelling(name: brand_name) { - with_authored_identity(identity: identity, structural: structural) + with_preserved_binding_id(identity: identity, structural: structural) } else { structural } } +type AliasPeelResult { + node: Node + diagnostics: List +} + // Peel alias bindings for call-site arg check: structural carrier with // reference-site brand identity (bounded A3 — not a full re-resolve). -fn peel_nominal_alias_identity(n: Node, env: TypeEnv, module_name: String) -> Node { +fn peel_nominal_alias_identity_result(n: Node, env: TypeEnv, module_name: String) -> AliasPeelResult { let source_indices = env.source_indices let brand = authored_name_at(source_indices: source_indices, node: n) + if is_declared_container_alias_spelling(name: brand) && n.children |> count > 0 { + AliasPeelResult { node: n, diagnostics: [] } + } else { match lookup_type_for(env: env, node: n) { Present { value: resolved } => - let structural = if resolved.connective == NoConnective && resolved.children |> count == 0 && resolved.inferred != none { + let structural_result = if resolved.connective == NoConnective && resolved.children |> count == 0 && resolved.inferred != none { match resolved.inferred { Present { value: Resolved { node: target } } => - resolve_node_bounded(n: target, env: env, module_name: module_name, depth: 0).resolved - _ => resolve_node_bounded(n: resolved, env: env, module_name: module_name, depth: 0).resolved + resolve_alias_target(target: target, env: env, module_name: module_name, depth: 0) + _ => resolve_node_bounded(n: resolved, env: env, module_name: module_name, depth: 0) } } else { - resolve_node_bounded(n: resolved, env: env, module_name: module_name, depth: 0).resolved + resolve_node_bounded(n: resolved, env: env, module_name: module_name, depth: 0) } - if brand != "" && brand != authored_name_at(source_indices: source_indices, node: structural) + let structural = structural_result.resolved + if resolved.binding_id != none && brand != "" && brand != authored_name_at(source_indices: source_indices, node: structural) && !is_declared_container_alias_spelling(name: brand) { - with_authored_identity(identity: n, structural: structural) + let branded = match resolved.inferred { + Present { value: Resolved { node: target } } => + if node_is_bare_type_ref(n: target) { + structural + } else { + with_preserved_binding_id(identity: resolved, structural: structural) + } + _ => with_preserved_binding_id(identity: resolved, structural: structural) + } + AliasPeelResult { node: branded, diagnostics: structural_result.diagnostics } } else if resolved.connective == NoConnective && resolved.children |> count == 0 && resolved.inferred != none { match resolved.inferred { Present { value: Resolved { node: target } } => - let target_resolved = resolve_node_bounded(n: target, env: env, module_name: module_name, depth: 0).resolved - with_authored_identity(identity: n, structural: target_resolved) - _ => resolved + let target_result = resolve_alias_target(target: target, env: env, module_name: module_name, depth: 0) + AliasPeelResult { node: target_result.resolved, diagnostics: concat(structural_result.diagnostics, target_result.diagnostics) } + _ => AliasPeelResult { node: resolved, diagnostics: structural_result.diagnostics } } - } else { resolved } - Absent => n + } else { AliasPeelResult { node: resolved, diagnostics: structural_result.diagnostics } } + Absent => AliasPeelResult { node: n, diagnostics: [] } + } } } +fn peel_nominal_alias_identity(n: Node, env: TypeEnv, module_name: String) -> Node { + peel_nominal_alias_identity_result(n: n, env: env, module_name: module_name).node +} + // ========================================================================= // Result types for type resolution // ========================================================================= @@ -178,19 +192,26 @@ fn is_user_generic_use_site(n: Node, env: TypeEnv) -> Bool { let has_structure = n.connective != NoConnective if has_structure { false } else { - match lookup_type_for(env: env, node: n) { - Present { value: decl } => - if decl.params |> count > 0 { + match lookup_decl_arity_for(env: env, node: n) { + Present { value: arity } => + if arity > 0 { // Container types (Map, List, Set, etc.) stay unexpanded regardless // of alias (INVARIANTS.md: "container_types controls which types stay // unexpanded during resolve"). Map = PartialFunction is an // inhabitation declaration, not an alias to expand. Algebra fields // are added on demand via enrich_kernel_type during method lookup. if is_container_type(name: authored_name(env: env, node: n)) { false } - else if decl.inferred != none { true } else { true } } else { false } - Absent => false + Absent => + match lookup_type_for(env: env, node: n) { + Present { value: decl } => + if decl.params |> count > 0 { + if is_container_type(name: authored_name(env: env, node: n)) { false } + else { true } + } else { false } + Absent => false + } } } } @@ -209,7 +230,8 @@ fn substitute_type_slots(n: Node, slot_bindings: Map, decl_name: S substitute_type_slots(n: arg, slot_bindings: slot_bindings, decl_name: decl_name, source_indices: source_indices) ) Node { - name: child.name, span: child.span, ident_span: child.ident_span, children: substituted_args, + name: child.name, ident: child.ident, binding_id: child.binding_id, + span: child.span, ident_span: child.ident_span, children: substituted_args, connective: child.connective, params: child.params, inferred: child.inferred, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, @@ -227,7 +249,8 @@ fn substitute_type_slots(n: Node, slot_bindings: Map, decl_name: S _ => n.inferred } Node { - name: n.name, span: n.span, ident_span: n.ident_span, children: new_children, + name: n.name, ident: n.ident, binding_id: n.binding_id, + span: n.span, ident_span: n.ident_span, children: new_children, connective: n.connective, params: n.params, inferred: new_inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, @@ -247,16 +270,34 @@ fn classify_alias(target: Node) -> AliasKind { else { AliasPassthrough } } -fn resolve_alias_target(target: Node, env: TypeEnv, module_name: String, depth: Int) -> Node { +fn resolve_alias_target(target: Node, env: TypeEnv, module_name: String, depth: Int) -> NodeResolveResult { + if depth > 100 { + return NodeResolveResult { + resolved: target, + diagnostics: [make_error_node(diagnostic: InternalError { message: concat("internal: alias resolution exceeded depth 100 for '", authored_name(env: env, node: target), "'"), span: target.span }, module_name: module_name)] + } + } match classify_alias(target: target) { AliasParameterized => - resolve_node_bounded(n: target, env: env, module_name: module_name, depth: depth + 1).resolved + resolve_node_bounded(n: target, env: env, module_name: module_name, depth: depth + 1) AliasLeaf => - match lookup_type_by_name(env: env, name: authored_name_at(source_indices: env.source_indices, node: target)) { - Present { value: env_target } => env_target - Absent => target + match lookup_type_for(env: env, node: target) { + Present { value: env_target } => + if env_target.connective == NoConnective && env_target.children |> count == 0 && env_target.inferred != none { + match env_target.inferred { + Present { value: Resolved { node: next_target } } => + if node_is_bare_type_ref(n: next_target) + && authored_name(env: env, node: next_target) == authored_name(env: env, node: env_target) { + NodeResolveResult { resolved: env_target, diagnostics: [] } + } else { + resolve_alias_target(target: next_target, env: env, module_name: module_name, depth: depth + 1) + } + _ => NodeResolveResult { resolved: env_target, diagnostics: [] } + } + } else { NodeResolveResult { resolved: env_target, diagnostics: [] } } + Absent => NodeResolveResult { resolved: target, diagnostics: [] } } - AliasPassthrough => target + AliasPassthrough => NodeResolveResult { resolved: target, diagnostics: [] } } } @@ -275,7 +316,8 @@ fn resolve_nominal_alias_rhs(n: Node, env: TypeEnv, module_name: String) -> Node let validation = resolve_node(n: n, env: env, module_name: module_name) NodeResolveResult { resolved: Node { - name: n.name, ident: n.ident, span: n.span, ident_span: n.ident_span, children: resolved_args, + name: n.name, ident: n.ident, binding_id: n.binding_id, + span: n.span, ident_span: n.ident_span, children: resolved_args, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, @@ -296,6 +338,27 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) } } let has_structure = n.connective != NoConnective + let env = if has_structure && n.transport == none && (n.params |> count) > 0 { + fold(n.params, init: env, f: (e, p) => + let tp_name = generic_param_name_at(n: p, source_indices: e.source_indices) + let tp_intern = intern(table: e.intern_table, s: tp_name) + TypeEnv { + bindings: map_insert(e.bindings, tp_intern.id, TypeBinding { + name: tp_name, + resolved: Node { name: tp_name, span: kernel_span(name: tp_name), ident_span: Present { value: kernel_span(name: tp_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: tp_name } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + provenance: SubValueUnknown + }), + carrier_bindings: e.carrier_bindings, + decl_registry: e.decl_registry, + duplicate_decl_ids: e.duplicate_decl_ids, + recursive_types: e.recursive_types, + recursive_type_set: e.recursive_type_set, + inductive_fields: e.inductive_fields, + source_indices: e.source_indices, + intern_table: tp_intern.table + } + ) + } else { env } if has_structure { let is_product = n.connective == Conj if is_product { @@ -306,7 +369,7 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) let base_resolved = base_result.resolved let base_diags = base_result.diagnostics NodeResolveResult { - resolved: Node { name: n.name, span: n.span, ident_span: n.ident_span, children: [base_resolved], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { name: n.name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: [base_resolved], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: base_diags } Absent => NodeResolveResult { resolved: n, diagnostics: [] } @@ -314,14 +377,33 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) } else { let child_results = map(n.children, child => if child.inferred == none { - NodeResolveResult { resolved: child, diagnostics: [] } + if child.children |> count > 0 { + let authored_type = field_node_type_expr(n: child) + let rt_result = resolve_node_bounded(n: authored_type, env: env, module_name: module_name, depth: depth + 1) + let rt_resolved = rt_result.resolved + let rt_diags = rt_result.diagnostics + let resolved_children = match field_node_default_value(n: child) { + Present { value: dv } => [rt_resolved, dv] + Absent => [rt_resolved] + } + NodeResolveResult { + resolved: Node { name: child.name, ident: child.ident, binding_id: child.binding_id, span: child.span, ident_span: child.ident_span, children: resolved_children, connective: child.connective, params: child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, rt_resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + diagnostics: rt_diags + } + } else { + NodeResolveResult { resolved: child, diagnostics: [] } + } } else { let child_rt = resolved_type(n: child) let rt_result = resolve_node_bounded(n: child_rt, env: env, module_name: module_name, depth: depth + 1) let rt_resolved = rt_result.resolved let rt_diags = rt_result.diagnostics - NodeResolveResult { - resolved: Node { name: child.name, span: child.span, ident_span: child.ident_span, children: child.children, connective: child.connective, params: child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, rt_resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + let resolved_children = match field_node_default_value(n: child) { + Present { value: dv } => [rt_resolved, dv] + Absent => [rt_resolved] + } + NodeResolveResult { + resolved: Node { name: child.name, ident: child.ident, binding_id: child.binding_id, span: child.span, ident_span: child.ident_span, children: resolved_children, connective: child.connective, params: child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, rt_resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: rt_diags } } @@ -329,7 +411,7 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) let resolved_children = map(child_results, cr => cr.resolved) let all_diags = flat_map(child_results, cr => cr.diagnostics) NodeResolveResult { - resolved: Node { name: n.name, span: n.span, ident_span: n.ident_span, children: resolved_children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { name: n.name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: resolved_children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: all_diags } } @@ -348,7 +430,22 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) let variant_results = map(n.children, variant_child => let field_results = map(variant_child.children, field_child => if field_child.inferred == none { - NodeResolveResult { resolved: field_child, diagnostics: [] } + if field_child.children |> count > 0 { + let authored_type = field_node_type_expr(n: field_child) + let rt_result = resolve_node_bounded(n: authored_type, env: env, module_name: module_name, depth: depth + 1) + let rt_resolved = rt_result.resolved + let rt_diags = rt_result.diagnostics + let resolved_children = match field_node_default_value(n: field_child) { + Present { value: dv } => [rt_resolved, dv] + Absent => [rt_resolved] + } + NodeResolveResult { + resolved: Node { name: field_child.name, ident: field_child.ident, binding_id: field_child.binding_id, span: field_child.span, ident_span: field_child.ident_span, children: resolved_children, connective: field_child.connective, params: field_child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: field_child.return_cardinality, uses: field_child.uses, body: field_child.body, transport: field_child.transport, properties: concat(field_child.properties, rt_resolved.properties), type_annotation: field_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + diagnostics: rt_diags + } + } else { + NodeResolveResult { resolved: field_child, diagnostics: [] } + } } else { let field_rt = resolved_type(n: field_child) let is_self_ref = authored_name(env: env, node: field_rt) == authored_name(env: env, node: n) && field_rt.children |> count > 0 @@ -359,8 +456,12 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) } let rt_resolved = rt_result.resolved let rt_diags = rt_result.diagnostics - NodeResolveResult { - resolved: Node { name: field_child.name, span: field_child.span, ident_span: field_child.ident_span, children: field_child.children, connective: field_child.connective, params: field_child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: field_child.return_cardinality, uses: field_child.uses, body: field_child.body, transport: field_child.transport, properties: concat(field_child.properties, rt_resolved.properties), type_annotation: field_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + let resolved_children = match field_node_default_value(n: field_child) { + Present { value: dv } => [rt_resolved, dv] + Absent => [rt_resolved] + } + NodeResolveResult { + resolved: Node { name: field_child.name, ident: field_child.ident, binding_id: field_child.binding_id, span: field_child.span, ident_span: field_child.ident_span, children: resolved_children, connective: field_child.connective, params: field_child.params, inferred: Present { value: Resolved { node: rt_resolved } }, return_cardinality: field_child.return_cardinality, uses: field_child.uses, body: field_child.body, transport: field_child.transport, properties: concat(field_child.properties, rt_resolved.properties), type_annotation: field_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: rt_diags } } @@ -368,14 +469,14 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) let resolved_fields = map(field_results, fr => fr.resolved) let field_diags = flat_map(field_results, fr => fr.diagnostics) NodeResolveResult { - resolved: Node { name: variant_child.name, span: variant_child.span, ident_span: variant_child.ident_span, children: resolved_fields, connective: variant_child.connective, params: variant_child.params, inferred: variant_child.inferred, return_cardinality: variant_child.return_cardinality, uses: variant_child.uses, body: variant_child.body, transport: variant_child.transport, properties: variant_child.properties, type_annotation: variant_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { name: variant_child.name, ident: variant_child.ident, binding_id: variant_child.binding_id, span: variant_child.span, ident_span: variant_child.ident_span, children: resolved_fields, connective: variant_child.connective, params: variant_child.params, inferred: variant_child.inferred, return_cardinality: variant_child.return_cardinality, uses: variant_child.uses, body: variant_child.body, transport: variant_child.transport, properties: variant_child.properties, type_annotation: variant_child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: field_diags } ) let resolved_variants = map(variant_results, vr => vr.resolved) let all_diags = flat_map(variant_results, vr => vr.diagnostics) NodeResolveResult { - resolved: Node { name: n.name, span: n.span, ident_span: n.ident_span, children: resolved_variants, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { name: n.name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: resolved_variants, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: all_diags } } @@ -383,7 +484,10 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) } else if n.children |> count > 0 && is_user_generic_use_site(n: n, env: env) { let type_name = authored_name(env: env, node: n) let decl = match lookup_type_for(env: env, node: n) { Present { value: d } => d Absent => n } - let expected_arity = decl.params |> count + let expected_arity = match lookup_decl_arity_for(env: env, node: n) { + Present { value: arity } => arity + Absent => decl.params |> count + } let actual_arity = n.children |> count let arity_diags = if expected_arity != actual_arity { [make_error_node(diagnostic: ArityMismatch { name: type_name, expected: expected_arity, got: actual_arity, span: n.span }, module_name: module_name)] @@ -407,17 +511,17 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) } let target_result = resolve_node_bounded(n: alias_target, env: env, module_name: module_name, depth: depth + 1) let is_recursive = is_recursive_type_by_name(env: env, name: type_name) - let expanded_node = Node { name: type_name, span: n.span, ident_span: n.ident_span, children: target_result.resolved.children, connective: target_result.resolved.connective, params: [], inferred: target_result.resolved.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: target_result.resolved.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } - let resolved_node = Node { name: type_name, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: expanded_node } }, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: target_result.resolved.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + let expanded_node = Node { name: type_name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: target_result.resolved.children, connective: target_result.resolved.connective, params: [], inferred: target_result.resolved.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: target_result.resolved.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + let resolved_node = Node { name: type_name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: expanded_node } }, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: target_result.resolved.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } NodeResolveResult { resolved: resolved_node, diagnostics: concat(arity_diags, arg_diags, target_result.diagnostics) } } else { let substituted_children = decl.children |> map(child => substitute_type_slots(n: child, slot_bindings: slot_bindings, decl_name: type_name, source_indices: env.source_indices) ) let is_recursive = is_recursive_type_by_name(env: env, name: type_name) - let expanded_node = Node { name: type_name, span: n.span, ident_span: n.ident_span, children: substituted_children, connective: decl.connective, params: [], inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: decl.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } - let result = NodeResolveResult { - resolved: Node { name: type_name, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: expanded_node } }, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: decl.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data }, + let expanded_node = Node { name: type_name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: substituted_children, connective: decl.connective, params: [], inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: decl.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data } + let result = NodeResolveResult { + resolved: Node { name: type_name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: resolved_args, connective: NoConnective, params: [], inferred: Present { value: Resolved { node: expanded_node } }, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: decl.properties, type_annotation: n.type_annotation, is_self_recursive: is_recursive, has_non_tail_self_call: n.has_non_tail_self_call, match_pattern: n.match_pattern, expr_data: n.expr_data }, diagnostics: concat(arity_diags, arg_diags) } result @@ -436,12 +540,12 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) let val_result = resolve_node_bounded(n: val_type, env: env, module_name: module_name, depth: depth + 1) let val_resolved = val_result.resolved let val_diags = val_result.diagnostics - let key_param_name = if key_child_node.inferred != none { authored_name(env: env, node: key_child_node) } else { match container_param_name(kind_name: type_name, index: 0) { Present { value: pn } => pn Absent => authored_name(env: env, node: key_child_node) } } - let val_param_name = if val_child_node.inferred != none { authored_name(env: env, node: val_child_node) } else { match container_param_name(kind_name: type_name, index: 1) { Present { value: pn } => pn Absent => authored_name(env: env, node: val_child_node) } } - let resolved_key_child = Node { name: key_param_name, span: key_child_node.span, ident_span: key_child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: key_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } - let resolved_val_child = Node { name: val_param_name, span: val_child_node.span, ident_span: val_child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: val_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let key_param_name = if key_child_node.inferred != none { authored_name(env: env, node: key_child_node) } else { match container_param_name(kind_name: type_name, index: 0) { Present { value: pn } => pn Absent => authored_name(env: env, node: key_child_node) } } + let val_param_name = if val_child_node.inferred != none { authored_name(env: env, node: val_child_node) } else { match container_param_name(kind_name: type_name, index: 1) { Present { value: pn } => pn Absent => authored_name(env: env, node: val_child_node) } } + let resolved_key_child = Node { name: key_param_name, ident: key_child_node.ident, binding_id: key_child_node.binding_id, span: key_child_node.span, ident_span: key_child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: key_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let resolved_val_child = Node { name: val_param_name, ident: val_child_node.ident, binding_id: val_child_node.binding_id, span: val_child_node.span, ident_span: val_child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: val_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } NodeResolveResult { - resolved: Node { name: type_name, span: n.span, ident_span: n.ident_span, children: [resolved_key_child, resolved_val_child], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { name: type_name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: [resolved_key_child, resolved_val_child], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: concat(key_diags, val_diags) } } else if n.children |> count == 1 { @@ -452,10 +556,10 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) let el_result = resolve_node_bounded(n: el_type, env: env, module_name: module_name, depth: depth + 1) let el_resolved = el_result.resolved let el_diags = el_result.diagnostics - let el_param_name = if child_node.inferred != none { authored_name(env: env, node: child_node) } else { match container_param_name(kind_name: type_name, index: 0) { Present { value: pn } => pn Absent => authored_name(env: env, node: child_node) } } - let resolved_child = Node { name: el_param_name, span: child_node.span, ident_span: child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: el_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } + let el_param_name = if child_node.inferred != none { authored_name(env: env, node: child_node) } else { match container_param_name(kind_name: type_name, index: 0) { Present { value: pn } => pn Absent => authored_name(env: env, node: child_node) } } + let resolved_child = Node { name: el_param_name, ident: child_node.ident, binding_id: child_node.binding_id, span: child_node.span, ident_span: child_node.ident_span, children: [], connective: NoConnective, params: [], inferred: Present { value: Resolved { node: el_resolved } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData } NodeResolveResult { - resolved: Node { name: type_name, span: n.span, ident_span: n.ident_span, children: [resolved_child], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + resolved: Node { name: type_name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: n.ident_span, children: [resolved_child], connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: el_diags } Absent => NodeResolveResult { resolved: n, diagnostics: [] } @@ -484,15 +588,21 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) // in env). Without this, optionality is silently discarded. let structurally_resolved = if resolved.connective == NoConnective && resolved.children |> count == 0 && resolved.inferred != none { match resolved.inferred { - Present { value: Resolved { node: target } } => target + Present { value: Resolved { node: target } } => + match lookup_type_for(env: env, node: target) { + Present { value: target_resolved } => target_resolved + Absent => target + } _ => resolved } } else { resolved } let is_optional = n.return_cardinality == CardOptional let final_resolved = if is_optional { with_optional_cardinality(n: structurally_resolved) } else { structurally_resolved } - NodeResolveResult { resolved: final_resolved, diagnostics: [] } - Absent => - let n_is_error = if n.inferred != none { is_compiler_error(inferred: n.inferred.value) } else { false } + let branded_resolved = preserve_nominal_brand_on_resolve( + identity: resolved, structural: final_resolved, brand_name: authored_name(env: env, node: n), source_indices: env.source_indices) + NodeResolveResult { resolved: branded_resolved, diagnostics: [] } + Absent => + let n_is_error = if n.inferred != none { is_compiler_error(inferred: n.inferred.value) } else { false } let n_is_callable = n.params |> count > 0 let n_is_type_var = if n.inferred != none { is_type_variable(inferred: n.inferred.value) } else { false } // Arrow nodes (callable types) handled by has_structure above. @@ -516,8 +626,19 @@ fn resolve_node_bounded(n: Node, env: TypeEnv, module_name: String, depth: Int) fn missing_generic_args_diagnostics(n: Node, env: TypeEnv, module_name: String) -> List { if n.children |> count == 0 && n.params |> count == 0 && is_user_generic_use_site(n: n, env: env) { let type_name = authored_name(env: env, node: n) - let decl = match lookup_type_for(env: env, node: n) { Present { value: d } => d Absent => n } - [make_error_node(diagnostic: ArityMismatch { name: type_name, expected: decl.params |> count, got: 0, span: n.span }, module_name: module_name)] + let expected = match lookup_decl_arity_for(env: env, node: n) { + Present { value: arity } => arity + Absent => + match lookup_type_for(env: env, node: n) { + Present { value: decl } => decl.params |> count + Absent => n.params |> count + } + } + if expected > 0 { + [make_error_node(diagnostic: ArityMismatch { name: type_name, expected: expected, got: 0, span: n.span }, module_name: module_name)] + } else { + [] + } } else { [] } @@ -580,8 +701,8 @@ fn resolve_param(param: Node, env: TypeEnv, module_name: String) -> ParamResult let authored_type = param_node_type_expr(n: param) let type_result = resolve_node(n: authored_type, env: env, module_name: module_name) let type_resolved = type_result.resolved - let rendered_type = if authored_type.children |> count > 0 { - Node { name: authored_type.name, span: authored_type.span, ident_span: authored_type.ident_span, children: type_resolved.children, connective: authored_type.connective, params: authored_type.params, inferred: Present { value: Resolved { node: type_resolved } }, return_cardinality: authored_type.return_cardinality, uses: authored_type.uses, body: authored_type.body, transport: authored_type.transport, properties: type_resolved.properties, type_annotation: authored_type.type_annotation, is_self_recursive: authored_type.is_self_recursive, has_non_tail_self_call: authored_type.has_non_tail_self_call, match_pattern: authored_type.match_pattern, expr_data: authored_type.expr_data } + let rendered_type = if authored_type.children |> count > 0 { + Node { name: authored_type.name, ident: authored_type.ident, binding_id: authored_type.binding_id, span: authored_type.span, ident_span: authored_type.ident_span, children: type_resolved.children, connective: authored_type.connective, params: authored_type.params, inferred: Present { value: Resolved { node: type_resolved } }, return_cardinality: authored_type.return_cardinality, uses: authored_type.uses, body: authored_type.body, transport: authored_type.transport, properties: type_resolved.properties, type_annotation: authored_type.type_annotation, is_self_recursive: authored_type.is_self_recursive, has_non_tail_self_call: authored_type.has_non_tail_self_call, match_pattern: authored_type.match_pattern, expr_data: authored_type.expr_data } } else { type_resolved } @@ -955,17 +1076,21 @@ fn resolve_item_types(item: Node, env: TypeEnv, module_name: String) -> ItemResu [make_error_node(diagnostic: InternalError { message: concat("type param name collides with a value param in fn '", authored_name_at(source_indices: env.source_indices, node: item), "' — a value param shares its name with a declared type param (e.g., `fn f(T: T)`). Rename the value param, or dissolve via ParamKind / params-slot partition."), span: item.span }, module_name: module_name)] } else { [] } let env = fold(tp_names, init: env, f: (e, tp_name) => + let tp_intern = intern(table: e.intern_table, s: tp_name) TypeEnv { - bindings: map_insert(e.bindings, intern(table: e.intern_table, s: tp_name).id, TypeBinding { + bindings: map_insert(e.bindings, tp_intern.id, TypeBinding { name: tp_name, resolved: Node { name: tp_name, span: kernel_span(name: tp_name), ident_span: Present { value: kernel_span(name: tp_name) }, children: [], connective: NoConnective, params: [], inferred: Present { value: TypeVariable { id: tp_name } }, return_cardinality: Required, uses: [], body: none, transport: none, properties: [], type_annotation: none, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, provenance: SubValueUnknown }), + carrier_bindings: e.carrier_bindings, + decl_registry: e.decl_registry, + duplicate_decl_ids: e.duplicate_decl_ids, recursive_types: e.recursive_types, recursive_type_set: e.recursive_type_set, inductive_fields: e.inductive_fields, source_indices: e.source_indices, - intern_table: e.intern_table + intern_table: tp_intern.table } ) let param_results = map(item.params, p => resolve_param(param: p, env: env, module_name: module_name)) @@ -1022,8 +1147,12 @@ fn resolve_item_types(item: Node, env: TypeEnv, module_name: String) -> ItemResu let authored_type = field_node_type_expr(n: child) let tr = resolve_node(n: authored_type, env: env, module_name: module_name) let type_diags = concat(tr.diagnostics, missing_generic_args_diagnostics(n: authored_type, env: env, module_name: module_name)) + let resolved_children = match field_node_default_value(n: child) { + Present { value: dv } => [tr.resolved, dv] + Absent => [tr.resolved] + } ItemResult { - item: Node { name: child.name, span: child.span, ident_span: child.ident_span, children: child.children, connective: child.connective, params: child.params, inferred: child.inferred, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, tr.resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + item: Node { name: child.name, ident: child.ident, binding_id: child.binding_id, span: child.span, ident_span: child.ident_span, children: resolved_children, connective: child.connective, params: child.params, inferred: child.inferred, return_cardinality: child.return_cardinality, uses: child.uses, body: child.body, transport: child.transport, properties: concat(child.properties, tr.resolved.properties), type_annotation: child.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: type_diags } ) @@ -1033,15 +1162,19 @@ fn resolve_item_types(item: Node, env: TypeEnv, module_name: String) -> ItemResu let authored_type = field_node_type_expr(n: field) let tr = resolve_node(n: authored_type, env: env, module_name: module_name) let type_diags = concat(tr.diagnostics, missing_generic_args_diagnostics(n: authored_type, env: env, module_name: module_name)) + let resolved_children = match field_node_default_value(n: field) { + Present { value: dv } => [tr.resolved, dv] + Absent => [tr.resolved] + } ItemResult { - item: Node { name: field.name, span: field.span, ident_span: field.ident_span, children: field.children, connective: field.connective, params: field.params, inferred: field.inferred, return_cardinality: field.return_cardinality, uses: field.uses, body: field.body, transport: field.transport, properties: concat(field.properties, tr.resolved.properties), type_annotation: field.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + item: Node { name: field.name, ident: field.ident, binding_id: field.binding_id, span: field.span, ident_span: field.ident_span, children: resolved_children, connective: field.connective, params: field.params, inferred: field.inferred, return_cardinality: field.return_cardinality, uses: field.uses, body: field.body, transport: field.transport, properties: concat(field.properties, tr.resolved.properties), type_annotation: field.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: type_diags } ) let resolved_fields = map(field_results, fr => fr.item) let field_diags = flat_map(field_results, fr => fr.diagnostics) ItemResult { - item: Node { name: variant.name, span: variant.span, ident_span: variant.ident_span, children: resolved_fields, connective: variant.connective, params: variant.params, inferred: variant.inferred, return_cardinality: variant.return_cardinality, uses: variant.uses, body: variant.body, transport: variant.transport, properties: variant.properties, type_annotation: variant.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, + item: Node { name: variant.name, ident: variant.ident, binding_id: variant.binding_id, span: variant.span, ident_span: variant.ident_span, children: resolved_fields, connective: variant.connective, params: variant.params, inferred: variant.inferred, return_cardinality: variant.return_cardinality, uses: variant.uses, body: variant.body, transport: variant.transport, properties: variant.properties, type_annotation: variant.type_annotation, is_self_recursive: false, has_non_tail_self_call: false, match_pattern: none, expr_data: NoExprData }, diagnostics: field_diags } ) @@ -1053,7 +1186,8 @@ fn resolve_item_types(item: Node, env: TypeEnv, module_name: String) -> ItemResu ItemResult { item: Node { - name: item.name, span: item.span, ident_span: item.ident_span, children: resolved_children, + name: item.name, ident: item.ident, binding_id: item.binding_id, + span: item.span, ident_span: item.ident_span, children: resolved_children, params: resolved_params, inferred: resolved_ret, return_cardinality: item.return_cardinality, uses: resolved_uses, body: resolved_body, diff --git a/src/v2/04_types.dag b/src/v2/04_types.dag index 30a697585d1..06eca9fb2c4 100644 --- a/src/v2/04_types.dag +++ b/src/v2/04_types.dag @@ -66,6 +66,42 @@ fn child_type_node(ch: Node) -> Node { if ch.inferred != none { resolved_type(n: ch) } else { ch } } +// 🟡 phase-1 alias-transparency predicate — owner/lane: +// Mgr-SOUNDNESS bare-alias carrier dissolution. Remove when Node exposes a +// canonical bare_alias_target accessor, so transparency reads that fact instead +// of rechecking the NoConnective/empty-children shape. +fn node_is_bare_type_ref(n: Node) -> Bool { + n.connective == NoConnective + && n.children |> count == 0 + && n.params |> count == 0 +} + +fn node_bare_alias_target_name(n: Node, source_indices: Map) -> String? { + if node_is_bare_type_ref(n: n) { + match n.inferred { + Present { value: Resolved { node: target } } => + if node_is_bare_type_ref(n: target) { + Present { value: authored_name_at(source_indices: source_indices, node: target) } + } else { none } + _ => none + } + } else { none } +} + +fn nodes_are_transparent_bare_alias_pair(left: Node, right: Node, source_indices: Map) -> Bool { + let left_name = authored_name_at(source_indices: source_indices, node: left) + let right_name = authored_name_at(source_indices: source_indices, node: right) + match node_bare_alias_target_name(n: left, source_indices: source_indices) { + Present { value: left_target } => + left_target == right_name + Absent => + match node_bare_alias_target_name(n: right, source_indices: source_indices) { + Present { value: right_target } => right_target == left_name + Absent => false + } + } +} + fn child_type_at(n: Node, index: Int) -> Node? { match n.children |> skip(index) |> first { Present { value: ch } => Present { value: child_type_node(ch: ch) } @@ -126,7 +162,7 @@ fn is_declared_container_alias_spelling(name: String) -> Bool { fn structural_carrier_template_name(n: Node, source_indices: Map) -> String { if n.name != "" { canonical_template_name(n: Node { - name: n.name, span: n.span, ident_span: Present { value: kernel_span(name: n.name) }, + name: n.name, ident: n.ident, binding_id: n.binding_id, span: n.span, ident_span: Present { value: kernel_span(name: n.name) }, children: n.children, connective: n.connective, params: n.params, inferred: n.inferred, return_cardinality: n.return_cardinality, uses: n.uses, body: n.body, transport: n.transport, properties: n.properties, type_annotation: n.type_annotation, @@ -138,6 +174,28 @@ fn structural_carrier_template_name(n: Node, source_indices: Map) -> Node? { + if n.connective == Disj && canonical_template_name(n: n, source_indices: source_indices) == "FreeMonoid" { + let cons_variant = find_child_named(n: n, name: "Cons", source_indices: source_indices) + match cons_variant { + Present { value: cons } => + let head_by_name = match find_child_named(n: cons, name: "head", source_indices: source_indices) { + Present { value: head_field } => Present { value: child_type_node(ch: head_field) } + Absent => none + } + match head_by_name { + Present { value: _ } => head_by_name + Absent => + match cons.children |> first { + Present { value: first_field } => Present { value: child_type_node(ch: first_field) } + Absent => none + } + } + Absent => none + } + } else { none } +} + // ========================================================================= // Type structure predicates (MM-2) // ========================================================================= @@ -145,7 +203,15 @@ fn structural_carrier_template_name(n: Node, source_indices: Map Bool { n.connective == Conj } fn is_coproduct_type(n: Node) -> Bool { n.connective == Disj } fn is_leaf_type(n: Node) -> Bool { n.connective == NoConnective } -fn is_unit_like(n: Node) -> Bool { n.connective == Conj && n.children |> count == 0 } +fn is_unit_like(n: Node) -> Bool { + (n.connective == Conj && n.children |> count == 0) + || (n.connective == NoConnective + && n.children |> count == 0 + // 🟡 bootstrap-kernel Unit bridge — owner/lane: Mgr-SOUNDNESS + // branch-join env lookup completion. Remove this name arm when stage0 + // branch joins resolve kernel Unit through TypeEnv before comparison. + && n.name == "Unit") +} fn is_fully_resolved(n: Node, source_indices: Map) -> Bool { let self_is_type_var = match n.inferred { Present { value: inf } => is_type_variable(inferred: inf) Absent => false } @@ -321,7 +387,7 @@ fn algebra_method_field(name: String, param_types: List, return_type: Node } fn enrich_base_with_fields(name: String, base: Node, fields: List) -> Node { - Node { name: name, span: base.span, ident_span: base.ident_span, children: fields, connective: Conj, params: base.params, inferred: base.inferred, return_cardinality: base.return_cardinality, uses: base.uses, body: base.body, transport: base.transport, properties: base.properties, type_annotation: base.type_annotation, is_self_recursive: base.is_self_recursive, has_non_tail_self_call: base.has_non_tail_self_call, match_pattern: base.match_pattern, expr_data: base.expr_data } + Node { name: name, ident: base.ident, binding_id: base.binding_id, span: base.span, ident_span: base.ident_span, children: fields, connective: Conj, params: base.params, inferred: base.inferred, return_cardinality: base.return_cardinality, uses: base.uses, body: base.body, transport: base.transport, properties: base.properties, type_annotation: base.type_annotation, is_self_recursive: base.is_self_recursive, has_non_tail_self_call: base.has_non_tail_self_call, match_pattern: base.match_pattern, expr_data: base.expr_data } } fn placeholder_type_node(name: String) -> Node { @@ -744,17 +810,75 @@ fn node_type_compatible(left: Node, right: Node, source_indices: Map first { + Present { value: left_ch } => + let left_el = child_type_node(ch: left_ch) + let right_el = free_monoid_coproduct_element(n: right, source_indices: source_indices).value + if is_unit_like(n: left_el) || is_unit_like(n: right_el) { true } + else { node_type_compatible(left: left_el, right: right_el, source_indices: source_indices) } + Absent => true + } + } + else if right_is_container && free_monoid_coproduct_element(n: left, source_indices: source_indices) != none { + match right.children |> first { + Present { value: right_ch } => + let left_el = free_monoid_coproduct_element(n: left, source_indices: source_indices).value + let right_el = child_type_node(ch: right_ch) + if is_unit_like(n: left_el) || is_unit_like(n: right_el) { true } + else { node_type_compatible(left: left_el, right: right_el, source_indices: source_indices) } + Absent => true + } + } + else if node_is_keyed_collection(n: left, source_indices: source_indices) + && node_is_keyed_collection(n: right, source_indices: source_indices) { + if authored_name_at(source_indices: source_indices, node: left) != authored_name_at(source_indices: source_indices, node: right) { false } + else if (left.children |> count) != 2 || (right.children |> count) != 2 { false } + else { + match left.children |> first { + Present { value: left_key_ch } => + match right.children |> first { + Present { value: right_key_ch } => + match left.children |> skip(1) |> first { + Present { value: left_val_ch } => + match right.children |> skip(1) |> first { + Present { value: right_val_ch } => + node_type_compatible( + left: child_type_node(ch: left_key_ch), + right: child_type_node(ch: right_key_ch), + source_indices: source_indices + ) + && node_type_compatible( + left: child_type_node(ch: left_val_ch), + right: child_type_node(ch: right_val_ch), + source_indices: source_indices + ) + Absent => false + } + Absent => false + } + Absent => false + } + Absent => false + } + } + } + else if ((canonical_template_name(n: left, source_indices: source_indices) == canonical_template_name(n: right, source_indices: source_indices)) && (left.children |> count == 1)) && (right.children |> count == 1) && (is_declared_container_alias_spelling(name: authored_name_at(source_indices: source_indices, node: left)) || is_declared_container_alias_spelling(name: authored_name_at(source_indices: source_indices, node: right))) { // Aliased sequence spellings — e.g. List (Container) vs FreeMonoid // (Node), which collection.dag declares the SAME type (List = FreeMonoid). - // They canonicalize to the same template but carry different surface - // names. Compare element types across the two reps. Fires - // ONLY when the names DIFFER but canonicalize equal, so same-named and - // genuinely-distinct types are untouched (minimal blast radius). + // Container shells are structural; compare element types across the two + // reps, including duplicate FreeMonoid shells reached through imported + // carriers. Element binding_id still enforces brand distinctions. match left.children |> first { Present { value: left_ch } => match right.children |> first { @@ -777,7 +901,27 @@ fn node_type_compatible(left: Node, right: Node, source_indices: Map + match right.binding_id { + Present { value: right_binding_id } => left_binding_id == right_binding_id + Absent => false + } + Absent => + match right.binding_id { + Present { value: _ } => false + // Phase-1 fallback is only for still-unbranded kernel/synthetic + // leaves. register_type_decl_binding stamps all user declarations + // at build_type_env authority; stamped nodes fail closed above. + Absent => authored_name_at(source_indices: source_indices, node: left) == authored_name_at(source_indices: source_indices, node: right) + } + } + } } } diff --git a/src/v2/05_emit.dag b/src/v2/05_emit.dag index 6c644c63b9c..1da5f0b28ba 100644 --- a/src/v2/05_emit.dag +++ b/src/v2/05_emit.dag @@ -18,7 +18,7 @@ module v2.compiler.emit import v2.std.core { - Node, ErrorNode, InferredNode, Resolved, CompilerError, TypeVariable, is_compiler_error, + BindingId, Node, ErrorNode, InferredNode, Resolved, CompilerError, TypeVariable, is_compiler_error, module_imports, module_items, param_node_name_at, param_node_type_expr, param_node_default_value, NewlineIndex, authored_name_at, empty_intern_table, @@ -63,7 +63,7 @@ import v2.std.core { CardOptional } -import v2.compiler.infer_env { TypeEnv, TypeBinding, authored_name } +import v2.compiler.infer_env { TypeEnv, TypeBinding, TypeDeclBinding, authored_name } import std.induction { InductiveField, SubValueUnknown } import v2.compiler.infer_types { resolved_type, child_type_node, emit_map_has, node_is_collection, node_is_keyed_collection, node_is_element_collection, normalize_access_type_node, for_each_element_type_node, is_unit_like, is_declared_container_alias_spelling } import std.types { is_container_type, container_template_algebra } @@ -303,9 +303,10 @@ fn emit_simple_string_interp(parts: List, target: RenderTarget, sour fn empty_emit_scope() -> InferScope { InferScope { - type_env: TypeEnv { bindings: empty_map(), recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: empty_map(), intern_table: empty_intern_table() }, + type_env: TypeEnv { bindings: empty_map(), carrier_bindings: empty_map(), decl_registry: empty_map(), duplicate_decl_ids: [], recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: empty_map(), intern_table: empty_intern_table() }, func_env: ResolvedFuncEnv { signatures: empty_map() }, locals: empty_map(), + variant_collisions: empty_map(), match_bound_names: empty_map(), module_name: "", service_registry: empty_map(), @@ -319,6 +320,7 @@ fn module_emit_scope(typed_module: TypedModule) -> InferScope { type_env: typed_module.type_env, func_env: typed_module.func_env, locals: empty_map(), + variant_collisions: empty_map(), match_bound_names: empty_map(), module_name: authored_name_at(source_indices: typed_module.type_env.source_indices, node: typed_module.module), service_registry: empty_map(), diff --git a/src/v2/05_emit_rust.dag b/src/v2/05_emit_rust.dag index 427b7005398..e947d1c5721 100644 --- a/src/v2/05_emit_rust.dag +++ b/src/v2/05_emit_rust.dag @@ -405,6 +405,16 @@ fn rust_nominal_identity_carrier_shape_eligible(n: Node, source_indices: Map count) == 0 && (n.params |> count) == 0 && n.connective == NoConnective } +// BINDING-ID-OPAQUE-NEWTYPE-BRIDGE: +// BindingId must lower to a private Rust tuple newtype with pub(crate) mint so +// declaration identity stays unforgeable until v2 type declarations can carry a +// first-class OpaqueNewtype/constructor-visibility property. Dissolution trigger: +// add that declaration property to the model and have the emitter consume it here; +// do not extend this bridge to another type name. +fn rust_binding_id_opaque_newtype_bridge(name: String) -> Bool { + name == "BindingId" +} + fn rust_diff_id_ord_carrier_shape_eligible(name: String, children: List, source_indices: Map) -> Bool { if name != "DiffId" || (children |> count) != 1 { false @@ -2779,6 +2789,15 @@ fn emit_type_def_from_connective(item: Node, recursive_types: Set, share fn emit_struct_from_children(name: String, type_params: String, generic_param_names: List, children: List, recursive_types: Set, shared_types: Set, env: TypeEnv, emit_info: EmitGraphInfo) -> String { + if rust_binding_id_opaque_newtype_bridge(name: name) { + return concat( + "#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]\n", + rust_visibility_prefix(), rust_items().struct_keyword, " BindingId(i64);\n\n", + "impl BindingId {\n", + " pub(crate) fn mint(value: i64) -> Self { BindingId(value) }\n", + "}" + ) + } let has_fn_fields = match map_get(emit_info.type_summaries, name) { Present { value: ts } => ts.has_fn_fields Absent => false @@ -5268,7 +5287,11 @@ fn emit_rust_first_method_call(receiver: Node, registry: Map, fn emit_rust_generic_method_call(method_name: String, receiver: Node, args: List, result_type: InferredNode?, registry: Map, scope: InferScope, depth: Int, shared_types: Set, emit_info: EmitGraphInfo) -> String { let function_name = method_name - if rust_receiver_has_callable_method_field(receiver: receiver, method_name: function_name, scope: scope) { + let receiver_type = resolved_type(n: receiver) + let receiver_type_name = authored_name_at(source_indices: scope.type_env.source_indices, node: receiver_type) + let runtime_container_method = map_contains_key(rt_functions(), function_name) + && (is_container_type(name: receiver_type_name) || node_is_keyed_collection(n: receiver_type, source_indices: scope.type_env.source_indices)) + if rust_receiver_has_callable_method_field(receiver: receiver, method_name: function_name, scope: scope) && !runtime_container_method { let recv_str = emit_typed_expr_base(texpr: receiver, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info) let arg_strs = args |> map(a => emit_cloned_arg(texpr: arg_value(n: a), registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info)) concat("(", recv_str, ".", emit_ident(name: function_name, target: Rust), ")(", arg_strs |> join(separator: ", "), ")") @@ -5751,6 +5774,14 @@ fn emit_typed_record_lit(type_name: String?, fields: List, parent_enum: St } Present { value: tn } => let si = scope.type_env.source_indices + if rust_binding_id_opaque_newtype_bridge(name: tn) { + match fields |> filter(f => field_init_node_name_at(n: f, source_indices: si) == "value") |> first { + Present { value: f } => + let inner = emit_typed_expr(texpr: field_init_node_value(n: f), registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024) + return concat("BindingId::mint(", inner, ")") + Absent => return "compile_error!(\"BindingId literal missing value\")" + } + } let context_lookup = contextual_variant_parent(variant_name: tn, parent_enum: parent_enum, resolved_type: resolved_type, emit_info: emit_info, source_indices: si) let effective_parent = match context_lookup { Present { value: context_parent } => Present { value: context_parent } diff --git a/src/v2/compiler_tests_rust.dag b/src/v2/compiler_tests_rust.dag index 86847d09704..9673f154b60 100644 --- a/src/v2/compiler_tests_rust.dag +++ b/src/v2/compiler_tests_rust.dag @@ -667,6 +667,7 @@ fn ct_rust_btree_set_ord_eligibility_test() -> String { " std::rc::Rc::new(crate::v2_std_core::Node {\n", " name: name.to_string(),\n", " ident: None,\n", + " binding_id: None,\n", " span: span.clone(),\n", " ident_span: Some(span),\n", " children: std::rc::Rc::new(children),\n", @@ -1372,6 +1373,7 @@ fn ct_profile_reconcile_test() -> String { " module_index.clone(),\n", " source_indices.clone(),\n", " intern_table.clone(),\n", + " crate::v2_compiler_infer::empty_binding_id_allocator(),\n", " );\n", " let env_elapsed = t_env.elapsed();\n", " let rss_after_env = get_rss_bytes();\n", @@ -1405,6 +1407,7 @@ fn ct_profile_reconcile_test() -> String { " module_index.clone(),\n", " source_indices.clone(),\n", " intern_table.clone(),\n", + " crate::v2_compiler_infer::empty_binding_id_allocator(),\n", " );\n", " let full_elapsed = t_full.elapsed();\n", " let rss_after = get_rss_bytes();\n", diff --git a/src/v2/stage0/src/compiler_tests.rs b/src/v2/stage0/src/compiler_tests.rs index 3fde97bc46b..b07194f003a 100644 --- a/src/v2/stage0/src/compiler_tests.rs +++ b/src/v2/stage0/src/compiler_tests.rs @@ -928,6 +928,7 @@ mod compiler_tests { std::rc::Rc::new(crate::v2_std_core::Node { name: name.to_string(), ident: None, + binding_id: None, span: span.clone(), ident_span: Some(span), children: std::rc::Rc::new(children), @@ -1784,6 +1785,7 @@ mod compiler_tests { module_index.clone(), source_indices.clone(), intern_table.clone(), + crate::v2_compiler_infer::empty_binding_id_allocator(), ); let env_elapsed = t_env.elapsed(); let rss_after_env = get_rss_bytes(); @@ -1820,6 +1822,7 @@ mod compiler_tests { module_index.clone(), source_indices.clone(), intern_table.clone(), + crate::v2_compiler_infer::empty_binding_id_allocator(), ); let full_elapsed = t_full.elapsed(); let rss_after = get_rss_bytes(); diff --git a/src/v2/stage0/src/std_types.rs b/src/v2/stage0/src/std_types.rs index d0f2b3f3dd2..90eaa8a4896 100644 --- a/src/v2/stage0/src/std_types.rs +++ b/src/v2/stage0/src/std_types.rs @@ -366,7 +366,7 @@ pub enum CredentialFlow { }, WorkloadIdentity { audience: NonEmptyStr, - service_account: Box>, + service_account: Option, scopes: Rc>, }, InteractiveAuth { @@ -517,7 +517,7 @@ pub enum AuthScheme { pub struct AccessToken { pub token: String, pub scheme: Rc, - pub expires_at: Box>, + pub expires_at: Option, } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] diff --git a/src/v2/stage0/src/v2_compiler_artifact.rs b/src/v2/stage0/src/v2_compiler_artifact.rs index 5d36cebe382..f2bc858ae87 100644 --- a/src/v2/stage0/src/v2_compiler_artifact.rs +++ b/src/v2/stage0/src/v2_compiler_artifact.rs @@ -127,7 +127,7 @@ pub type DagNodeId = String; #[serde(tag = "_variant")] pub enum DagInferredRecord { ResolvedRef { - node: Box, + node: DagNodeId, }, TypeVariableRef { id: String, @@ -140,7 +140,7 @@ pub enum DagInferredRecord { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct DagModuleRef { - pub module: Box, + pub module: DagNodeId, pub items: Rc>, pub item_registry_keys: Rc>, } diff --git a/src/v2/stage0/src/v2_compiler_compiler_tests_rust.rs b/src/v2/stage0/src/v2_compiler_compiler_tests_rust.rs index beae3f55534..acecad7ead1 100644 --- a/src/v2/stage0/src/v2_compiler_compiler_tests_rust.rs +++ b/src/v2/stage0/src/v2_compiler_compiler_tests_rust.rs @@ -101,7 +101,7 @@ pub fn ct_coercion_tests() -> String { } pub fn ct_rust_btree_set_ord_eligibility_test() -> String { - v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(" fn shaped_type_node(name: &str, children: Vec>) -> std::rc::Rc {\n".to_string(), " let span = crate::v2_std_core::make_span(0, name.len() as i64);\n".to_string()), " std::rc::Rc::new(crate::v2_std_core::Node {\n".to_string()), " name: name.to_string(),\n".to_string()), " ident: None,\n".to_string()), " span: span.clone(),\n".to_string()), " ident_span: Some(span),\n".to_string()), " children: std::rc::Rc::new(children),\n".to_string()), " connective: crate::v2_std_core::Connective::NoConnective,\n".to_string()), " params: std::rc::Rc::new(Vec::new()),\n".to_string()), " inferred: None,\n".to_string()), " return_cardinality: crate::v2_std_core::Cardinality::Required,\n".to_string()), " uses: std::rc::Rc::new(Vec::new()),\n".to_string()), " body: None,\n".to_string()), " transport: None,\n".to_string()), " properties: std::rc::Rc::new(Vec::new()),\n".to_string()), " type_annotation: None,\n".to_string()), " is_self_recursive: false,\n".to_string()), " has_non_tail_self_call: false,\n".to_string()), " match_pattern: None,\n".to_string()), " expr_data: std::rc::Rc::new(crate::v2_std_core::ExprData::NoExprData),\n".to_string()), " })\n".to_string()), " }\n\n".to_string()), " fn named_type_node(name: &str) -> std::rc::Rc {\n".to_string()), " shaped_type_node(name, Vec::new())\n".to_string()), " }\n\n".to_string()), " #[test]\n".to_string()), " fn rust_btree_set_ord_eligibility_requires_nominal_carrier_shape() {\n".to_string()), " let source_indices = std::rc::Rc::new(HashMap::new());\n".to_string()), " let symbol = named_type_node(\"Symbol\");\n".to_string()), " let diff_id = shaped_type_node(\"DiffId\", vec![symbol.clone()]);\n".to_string()), " assert!(\n".to_string()), " crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " symbol.clone(),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " diff_id.clone(),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " shaped_type_node(\"Symbol\", vec![named_type_node(\"Float\")]),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " shaped_type_node(\"DiffId\", vec![named_type_node(\"Float\")]),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " named_type_node(\"TestClaimId\"),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " }\n\n".to_string()) + v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(" fn shaped_type_node(name: &str, children: Vec>) -> std::rc::Rc {\n".to_string(), " let span = crate::v2_std_core::make_span(0, name.len() as i64);\n".to_string()), " std::rc::Rc::new(crate::v2_std_core::Node {\n".to_string()), " name: name.to_string(),\n".to_string()), " ident: None,\n".to_string()), " binding_id: None,\n".to_string()), " span: span.clone(),\n".to_string()), " ident_span: Some(span),\n".to_string()), " children: std::rc::Rc::new(children),\n".to_string()), " connective: crate::v2_std_core::Connective::NoConnective,\n".to_string()), " params: std::rc::Rc::new(Vec::new()),\n".to_string()), " inferred: None,\n".to_string()), " return_cardinality: crate::v2_std_core::Cardinality::Required,\n".to_string()), " uses: std::rc::Rc::new(Vec::new()),\n".to_string()), " body: None,\n".to_string()), " transport: None,\n".to_string()), " properties: std::rc::Rc::new(Vec::new()),\n".to_string()), " type_annotation: None,\n".to_string()), " is_self_recursive: false,\n".to_string()), " has_non_tail_self_call: false,\n".to_string()), " match_pattern: None,\n".to_string()), " expr_data: std::rc::Rc::new(crate::v2_std_core::ExprData::NoExprData),\n".to_string()), " })\n".to_string()), " }\n\n".to_string()), " fn named_type_node(name: &str) -> std::rc::Rc {\n".to_string()), " shaped_type_node(name, Vec::new())\n".to_string()), " }\n\n".to_string()), " #[test]\n".to_string()), " fn rust_btree_set_ord_eligibility_requires_nominal_carrier_shape() {\n".to_string()), " let source_indices = std::rc::Rc::new(HashMap::new());\n".to_string()), " let symbol = named_type_node(\"Symbol\");\n".to_string()), " let diff_id = shaped_type_node(\"DiffId\", vec![symbol.clone()]);\n".to_string()), " assert!(\n".to_string()), " crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " symbol.clone(),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " diff_id.clone(),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " shaped_type_node(\"Symbol\", vec![named_type_node(\"Float\")]),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " shaped_type_node(\"DiffId\", vec![named_type_node(\"Float\")]),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " assert!(\n".to_string()), " !crate::v2_compiler_emit_rust::rust_btree_set_element_ord_eligible(\n".to_string()), " named_type_node(\"TestClaimId\"),\n".to_string()), " source_indices.clone()\n".to_string()), " )\n".to_string()), " );\n".to_string()), " }\n\n".to_string()) } pub fn render_target_rust_enum(target: RenderTarget) -> String { @@ -295,7 +295,7 @@ pub fn ct_profile_full_pipeline_test() -> String { } pub fn ct_profile_reconcile_test() -> String { - v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(" #[test]\n".to_string(), " #[ignore]\n".to_string()), " fn profile_reconcile_per_module() {\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(64 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " use std::collections::HashMap;\n".to_string()), " use std::time::Instant;\n\n".to_string()), " let sources = self_compile_sources();\n\n".to_string()), " eprintln!(\n".to_string()), " \"\\n=== PER-MODULE RECONCILE PROFILE ({} sources) ===\",\n".to_string()), " sources.len()\n".to_string()), " );\n\n".to_string()), " let t0 = Instant::now();\n".to_string()), " let mut modules = Vec::new();\n".to_string()), " let mut intern_table = crate::v2_std_core::empty_intern_table();\n".to_string()), " for source in &sources {\n".to_string()), " let tokens = crate::v2_compiler_tokenize::tokenize(\n".to_string()), " source.content.clone(),\n".to_string()), " source.path.clone(),\n".to_string()), " );\n".to_string()), " let si = crate::v2_std_core::build_newline_index(\n".to_string()), " source.path.clone(),\n".to_string()), " source.content.clone(),\n".to_string()), " );\n".to_string()), " let parsed = crate::v2_compiler_parse::parse_with_table(\n".to_string()), " tokens.clone(),\n".to_string()), " crate::v2_rt::rc_map_insert(\n".to_string()), " crate::v2_rt::rc_empty_map::>(),\n".to_string()), " si.file.clone(),\n".to_string()), " si.clone(),\n".to_string()), " ),\n".to_string()), " intern_table.clone(),\n".to_string()), " );\n".to_string()), " let result = parsed.result.clone();\n".to_string()), " intern_table = parsed.intern_table.clone();\n".to_string()), " let m = result.module.clone()\n".to_string()), " .unwrap_or_else(|| panic!(\"parse failed for source {}\", source.path));\n".to_string()), " modules.push(m);\n".to_string()), " }\n".to_string()), " let resolve_si = sources.iter().fold(\n".to_string()), " crate::v2_rt::rc_empty_map::>(),\n".to_string()), " |acc, s| crate::v2_rt::rc_map_insert(acc, s.path.clone(), crate::v2_std_core::build_newline_index(s.path.clone(), s.content.clone())),\n".to_string()), " );\n".to_string()), " let graph = crate::v2_compiler_resolve::resolve_modules(std::rc::Rc::new(modules), resolve_si);\n".to_string()), " let setup_time = t0.elapsed();\n".to_string()), " let rss_baseline = get_rss_bytes();\n".to_string()), " eprintln!(\n".to_string()), " \" Setup (tok+parse+resolve): {:?} | RSS: {}\",\n".to_string()), " setup_time,\n".to_string()), " format_bytes(rss_baseline)\n".to_string()), " );\n".to_string()), " eprintln!(\" Modules to reconcile: {}\\n\", graph.modules.len());\n\n".to_string()), " let mut mi_raw = HashMap::<\n".to_string()), " String,\n".to_string()), " std::rc::Rc,\n".to_string()), " >::new();\n".to_string()), " let source_indices = std::rc::Rc::new(sources.iter().fold(\n".to_string()), " HashMap::>::new(),\n".to_string()), " |mut acc, source| {\n".to_string()), " acc.insert(\n".to_string()), " source.path.clone(),\n".to_string()), " crate::v2_std_core::build_newline_index(\n".to_string()), " source.path.clone(),\n".to_string()), " source.content.clone(),\n".to_string()), " ),\n".to_string()), " );\n".to_string()), " acc\n".to_string()), " },\n".to_string()), " ));\n\n".to_string()), " for resolved in graph.modules.iter() {\n".to_string()), " let name = resolved.module.name.to_string();\n".to_string()), " let item_count =\n".to_string()), " crate::v2_std_core::module_items(resolved.module.clone()).len();\n".to_string()), " let rss_before = get_rss_bytes();\n\n".to_string()), " eprint!(\" {:>35} ({:>3} items) ... \", name, item_count);\n\n".to_string()), " let module_index = std::rc::Rc::new(mi_raw.clone());\n\n".to_string()), " let t_unres = Instant::now();\n".to_string()), " let _unres = crate::v2_compiler_infer::build_type_env_unresolved(\n".to_string()), " resolved.clone(),\n".to_string()), " module_index.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " intern_table.clone(),\n".to_string()), " );\n".to_string()), " let unres_elapsed = t_unres.elapsed();\n".to_string()), " let rss_after_unres = get_rss_bytes();\n".to_string()), " let unres_delta = rss_after_unres.saturating_sub(rss_before);\n\n".to_string()), " eprint!(\n".to_string()), " \"cycles={:>8.2?}(+{}) \",\n".to_string()), " unres_elapsed,\n".to_string()), " format_bytes(unres_delta)\n".to_string()), " );\n\n".to_string()), " if unres_delta > 256 * 1024 * 1024 {\n".to_string()), " eprintln!(\"\");\n".to_string()), " panic!(\n".to_string()), " \"ABORT: '{}' cycle detection grew RSS by {}\",\n".to_string()), " name,\n".to_string()), " format_bytes(unres_delta)\n".to_string()), " );\n".to_string()), " }\n\n".to_string()), " let t_env = Instant::now();\n".to_string()), " let env_result = crate::v2_compiler_infer::build_type_env(\n".to_string()), " resolved.clone(),\n".to_string()), " module_index.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " intern_table.clone(),\n".to_string()), " );\n".to_string()), " let env_elapsed = t_env.elapsed();\n".to_string()), " let rss_after_env = get_rss_bytes();\n".to_string()), " let env_delta = rss_after_env.saturating_sub(rss_before);\n".to_string()), " let env_errs: usize = env_result\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v2_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .count();\n\n".to_string()), " eprint!(\n".to_string()), " \"env={:>8.2?}(+{},e={}) \",\n".to_string()), " env_elapsed,\n".to_string()), " format_bytes(env_delta),\n".to_string()), " env_errs\n".to_string()), " );\n\n".to_string()), " if env_delta > 512 * 1024 * 1024 {\n".to_string()), " eprintln!(\"\");\n".to_string()), " panic!(\n".to_string()), " \"ABORT: '{}' build_type_env grew RSS by {}\",\n".to_string()), " name,\n".to_string()), " format_bytes(env_delta)\n".to_string()), " );\n".to_string()), " }\n".to_string()), " if env_elapsed.as_secs() > 10 {\n".to_string()), " eprintln!(\"\");\n".to_string()), " panic!(\"ABORT: '{}' build_type_env took {:?}\", name, env_elapsed);\n".to_string()), " }\n\n".to_string()), " let t_full = Instant::now();\n".to_string()), " let tc_result = crate::v2_compiler_infer::typecheck_module(\n".to_string()), " resolved.clone(),\n".to_string()), " module_index.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " intern_table.clone(),\n".to_string()), " );\n".to_string()), " let full_elapsed = t_full.elapsed();\n".to_string()), " let rss_after = get_rss_bytes();\n".to_string()), " let delta = rss_after.saturating_sub(rss_before);\n".to_string()), " let diag_count: usize = tc_result\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v2_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .count();\n\n".to_string()), " eprintln!(\n".to_string()), " \"full={:>8.2?} | RSS: {} (+{}) | errs: {}\",\n".to_string()), " full_elapsed,\n".to_string()), " format_bytes(rss_after),\n".to_string()), " format_bytes(delta),\n".to_string()), " diag_count\n".to_string()), " );\n\n".to_string()), " if delta > 512 * 1024 * 1024 {\n".to_string()), " panic!(\n".to_string()), " \"ABORT: '{}' grew RSS by {} (>512MB)\",\n".to_string()), " name,\n".to_string()), " format_bytes(delta)\n".to_string()), " );\n".to_string()), " }\n".to_string()), " if full_elapsed.as_secs() > 10 {\n".to_string()), " panic!(\"ABORT: '{}' took {:?} (>10s)\", name, full_elapsed);\n".to_string()), " }\n\n".to_string()), " let typed = tc_result.typed.clone();\n".to_string()), " mi_raw.insert(name, typed);\n".to_string()), " }\n\n".to_string()), " let rss_final = get_rss_bytes();\n".to_string()), " eprintln!(\n".to_string()), " \"\\n RSS final: {} (from baseline: +{})\",\n".to_string()), " format_bytes(rss_final),\n".to_string()), " format_bytes(rss_final.saturating_sub(rss_baseline))\n".to_string()), " );\n".to_string()), " eprintln!(\"=== DONE ===\\n\");\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"profile_reconcile_per_module panicked\");\n".to_string()), " }\n\n".to_string()) + v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(" #[test]\n".to_string(), " #[ignore]\n".to_string()), " fn profile_reconcile_per_module() {\n".to_string()), " let result = std::thread::Builder::new()\n".to_string()), " .stack_size(64 * 1024 * 1024)\n".to_string()), " .spawn(|| {\n".to_string()), " use std::collections::HashMap;\n".to_string()), " use std::time::Instant;\n\n".to_string()), " let sources = self_compile_sources();\n\n".to_string()), " eprintln!(\n".to_string()), " \"\\n=== PER-MODULE RECONCILE PROFILE ({} sources) ===\",\n".to_string()), " sources.len()\n".to_string()), " );\n\n".to_string()), " let t0 = Instant::now();\n".to_string()), " let mut modules = Vec::new();\n".to_string()), " let mut intern_table = crate::v2_std_core::empty_intern_table();\n".to_string()), " for source in &sources {\n".to_string()), " let tokens = crate::v2_compiler_tokenize::tokenize(\n".to_string()), " source.content.clone(),\n".to_string()), " source.path.clone(),\n".to_string()), " );\n".to_string()), " let si = crate::v2_std_core::build_newline_index(\n".to_string()), " source.path.clone(),\n".to_string()), " source.content.clone(),\n".to_string()), " );\n".to_string()), " let parsed = crate::v2_compiler_parse::parse_with_table(\n".to_string()), " tokens.clone(),\n".to_string()), " crate::v2_rt::rc_map_insert(\n".to_string()), " crate::v2_rt::rc_empty_map::>(),\n".to_string()), " si.file.clone(),\n".to_string()), " si.clone(),\n".to_string()), " ),\n".to_string()), " intern_table.clone(),\n".to_string()), " );\n".to_string()), " let result = parsed.result.clone();\n".to_string()), " intern_table = parsed.intern_table.clone();\n".to_string()), " let m = result.module.clone()\n".to_string()), " .unwrap_or_else(|| panic!(\"parse failed for source {}\", source.path));\n".to_string()), " modules.push(m);\n".to_string()), " }\n".to_string()), " let resolve_si = sources.iter().fold(\n".to_string()), " crate::v2_rt::rc_empty_map::>(),\n".to_string()), " |acc, s| crate::v2_rt::rc_map_insert(acc, s.path.clone(), crate::v2_std_core::build_newline_index(s.path.clone(), s.content.clone())),\n".to_string()), " );\n".to_string()), " let graph = crate::v2_compiler_resolve::resolve_modules(std::rc::Rc::new(modules), resolve_si);\n".to_string()), " let setup_time = t0.elapsed();\n".to_string()), " let rss_baseline = get_rss_bytes();\n".to_string()), " eprintln!(\n".to_string()), " \" Setup (tok+parse+resolve): {:?} | RSS: {}\",\n".to_string()), " setup_time,\n".to_string()), " format_bytes(rss_baseline)\n".to_string()), " );\n".to_string()), " eprintln!(\" Modules to reconcile: {}\\n\", graph.modules.len());\n\n".to_string()), " let mut mi_raw = HashMap::<\n".to_string()), " String,\n".to_string()), " std::rc::Rc,\n".to_string()), " >::new();\n".to_string()), " let source_indices = std::rc::Rc::new(sources.iter().fold(\n".to_string()), " HashMap::>::new(),\n".to_string()), " |mut acc, source| {\n".to_string()), " acc.insert(\n".to_string()), " source.path.clone(),\n".to_string()), " crate::v2_std_core::build_newline_index(\n".to_string()), " source.path.clone(),\n".to_string()), " source.content.clone(),\n".to_string()), " ),\n".to_string()), " );\n".to_string()), " acc\n".to_string()), " },\n".to_string()), " ));\n\n".to_string()), " for resolved in graph.modules.iter() {\n".to_string()), " let name = resolved.module.name.to_string();\n".to_string()), " let item_count =\n".to_string()), " crate::v2_std_core::module_items(resolved.module.clone()).len();\n".to_string()), " let rss_before = get_rss_bytes();\n\n".to_string()), " eprint!(\" {:>35} ({:>3} items) ... \", name, item_count);\n\n".to_string()), " let module_index = std::rc::Rc::new(mi_raw.clone());\n\n".to_string()), " let t_unres = Instant::now();\n".to_string()), " let _unres = crate::v2_compiler_infer::build_type_env_unresolved(\n".to_string()), " resolved.clone(),\n".to_string()), " module_index.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " intern_table.clone(),\n".to_string()), " );\n".to_string()), " let unres_elapsed = t_unres.elapsed();\n".to_string()), " let rss_after_unres = get_rss_bytes();\n".to_string()), " let unres_delta = rss_after_unres.saturating_sub(rss_before);\n\n".to_string()), " eprint!(\n".to_string()), " \"cycles={:>8.2?}(+{}) \",\n".to_string()), " unres_elapsed,\n".to_string()), " format_bytes(unres_delta)\n".to_string()), " );\n\n".to_string()), " if unres_delta > 256 * 1024 * 1024 {\n".to_string()), " eprintln!(\"\");\n".to_string()), " panic!(\n".to_string()), " \"ABORT: '{}' cycle detection grew RSS by {}\",\n".to_string()), " name,\n".to_string()), " format_bytes(unres_delta)\n".to_string()), " );\n".to_string()), " }\n\n".to_string()), " let t_env = Instant::now();\n".to_string()), " let env_result = crate::v2_compiler_infer::build_type_env(\n".to_string()), " resolved.clone(),\n".to_string()), " module_index.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " intern_table.clone(),\n".to_string()), " crate::v2_compiler_infer::empty_binding_id_allocator(),\n".to_string()), " );\n".to_string()), " let env_elapsed = t_env.elapsed();\n".to_string()), " let rss_after_env = get_rss_bytes();\n".to_string()), " let env_delta = rss_after_env.saturating_sub(rss_before);\n".to_string()), " let env_errs: usize = env_result\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v2_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .count();\n\n".to_string()), " eprint!(\n".to_string()), " \"env={:>8.2?}(+{},e={}) \",\n".to_string()), " env_elapsed,\n".to_string()), " format_bytes(env_delta),\n".to_string()), " env_errs\n".to_string()), " );\n\n".to_string()), " if env_delta > 512 * 1024 * 1024 {\n".to_string()), " eprintln!(\"\");\n".to_string()), " panic!(\n".to_string()), " \"ABORT: '{}' build_type_env grew RSS by {}\",\n".to_string()), " name,\n".to_string()), " format_bytes(env_delta)\n".to_string()), " );\n".to_string()), " }\n".to_string()), " if env_elapsed.as_secs() > 10 {\n".to_string()), " eprintln!(\"\");\n".to_string()), " panic!(\"ABORT: '{}' build_type_env took {:?}\", name, env_elapsed);\n".to_string()), " }\n\n".to_string()), " let t_full = Instant::now();\n".to_string()), " let tc_result = crate::v2_compiler_infer::typecheck_module(\n".to_string()), " resolved.clone(),\n".to_string()), " module_index.clone(),\n".to_string()), " source_indices.clone(),\n".to_string()), " intern_table.clone(),\n".to_string()), " crate::v2_compiler_infer::empty_binding_id_allocator(),\n".to_string()), " );\n".to_string()), " let full_elapsed = t_full.elapsed();\n".to_string()), " let rss_after = get_rss_bytes();\n".to_string()), " let delta = rss_after.saturating_sub(rss_before);\n".to_string()), " let diag_count: usize = tc_result\n".to_string()), " .diagnostics\n".to_string()), " .iter()\n".to_string()), " .filter(|d| crate::v2_std_core::is_error_diagnostic(d.diagnostic.clone()))\n".to_string()), " .count();\n\n".to_string()), " eprintln!(\n".to_string()), " \"full={:>8.2?} | RSS: {} (+{}) | errs: {}\",\n".to_string()), " full_elapsed,\n".to_string()), " format_bytes(rss_after),\n".to_string()), " format_bytes(delta),\n".to_string()), " diag_count\n".to_string()), " );\n\n".to_string()), " if delta > 512 * 1024 * 1024 {\n".to_string()), " panic!(\n".to_string()), " \"ABORT: '{}' grew RSS by {} (>512MB)\",\n".to_string()), " name,\n".to_string()), " format_bytes(delta)\n".to_string()), " );\n".to_string()), " }\n".to_string()), " if full_elapsed.as_secs() > 10 {\n".to_string()), " panic!(\"ABORT: '{}' took {:?} (>10s)\", name, full_elapsed);\n".to_string()), " }\n\n".to_string()), " let typed = tc_result.typed.clone();\n".to_string()), " mi_raw.insert(name, typed);\n".to_string()), " }\n\n".to_string()), " let rss_final = get_rss_bytes();\n".to_string()), " eprintln!(\n".to_string()), " \"\\n RSS final: {} (from baseline: +{})\",\n".to_string()), " format_bytes(rss_final),\n".to_string()), " format_bytes(rss_final.saturating_sub(rss_baseline))\n".to_string()), " );\n".to_string()), " eprintln!(\"=== DONE ===\\n\");\n".to_string()), " })\n".to_string()), " .expect(\"failed to spawn thread\")\n".to_string()), " .join();\n".to_string()), " result.expect(\"profile_reconcile_per_module panicked\");\n".to_string()), " }\n\n".to_string()) } pub fn ct_module_footer() -> String { diff --git a/src/v2/stage0/src/v2_compiler_complexity.rs b/src/v2/stage0/src/v2_compiler_complexity.rs index 1d321f62305..77220859893 100644 --- a/src/v2/stage0/src/v2_compiler_complexity.rs +++ b/src/v2/stage0/src/v2_compiler_complexity.rs @@ -402,26 +402,29 @@ pub fn parser_state_param( ) .iter() .cloned() - .fold(None, |acc: _, pair: (i64, Rc)| { - if (acc.clone() != None) { - acc.clone() - } else { - { - let idx = pair.0.clone(); - let param = pair.1.clone(); - if (authored_name_at(si.clone(), param_node_type_expr(param.clone())).as_str() - == "ParserState".to_string().as_str()) + .fold( + None, + |acc: Option>, pair: (i64, Rc)| { + if (acc.clone() != None) { + acc.clone() + } else { { - Some(Rc::new(ParserStateParam { - name: param_node_name_at(param.clone(), si.clone()), - index: idx.clone(), - })) - } else { - None + let idx = pair.0.clone(); + let param = pair.1.clone(); + if (authored_name_at(si.clone(), param_node_type_expr(param.clone())).as_str() + == "ParserState".to_string().as_str()) + { + Some(Rc::new(ParserStateParam { + name: param_node_name_at(param.clone(), si.clone()), + index: idx.clone(), + })) + } else { + None + } } } - } - }) + }, + ) } pub fn parser_state_base_var( @@ -493,7 +496,7 @@ pub fn parser_state_arg_expr( ) .iter() .cloned() - .fold(None, |acc: _, pair: (i64, Rc)| { + .fold(None, |acc: Option>, pair: (i64, Rc)| { if (acc.clone() != None) { acc.clone() } else { @@ -2929,18 +2932,20 @@ pub fn consuming_tokens_arg( .clone() .iter() .cloned() - .fold(None, |acc: _, child: Rc| match acc.clone() { - Some(_) => acc.clone(), - None => match arg_name_at(child.clone(), si.clone()) { - Some(name) => { - if (name.clone().as_str() == "tokens".to_string().as_str()) { - Some(arg_value(child.clone())) - } else { - None + .fold(None, |acc: Option>, child: Rc| { + match acc.clone() { + Some(_) => acc.clone(), + None => match arg_name_at(child.clone(), si.clone()) { + Some(name) => { + if (name.clone().as_str() == "tokens".to_string().as_str()) { + Some(arg_value(child.clone())) + } else { + None + } } - } - None => None, - }, + None => None, + }, + } }) } @@ -4906,11 +4911,9 @@ pub fn collect_evidence_incremental( merge_optional_evidence(recv_ev, args_ev) } } else { - body.children - .clone() - .iter() - .cloned() - .fold(None, |acc: _, child: Rc| { + body.children.clone().iter().cloned().fold( + None, + |acc: Option, child: Rc| { let ce = collect_evidence_incremental( child.clone(), func_name.clone(), @@ -4922,15 +4925,13 @@ pub fn collect_evidence_incremental( si.clone(), ); merge_optional_evidence(acc.clone(), ce.clone()) - }) + }, + ) } } - _ => body - .children - .clone() - .iter() - .cloned() - .fold(None, |acc: _, child: Rc| { + _ => body.children.clone().iter().cloned().fold( + None, + |acc: Option, child: Rc| { let ce = collect_evidence_incremental( child.clone(), func_name.clone(), @@ -4942,7 +4943,8 @@ pub fn collect_evidence_incremental( si.clone(), ); merge_optional_evidence(acc.clone(), ce.clone()) - }), + }, + ), } }) } @@ -5144,10 +5146,9 @@ pub fn construct_branching_termination_proof( params: Rc>>, si: Rc>>, ) -> Option> { - params - .iter() - .cloned() - .fold(None, |best: _, p: Rc| match best.clone() { + params.iter().cloned().fold( + None, + |best: Option>, p: Rc| match best.clone() { Some(_) => best.clone(), None => { let pname = param_node_name_at(p.clone(), si.clone()); @@ -5229,7 +5230,8 @@ pub fn construct_branching_termination_proof( } } } - }) + }, + ) } pub fn proof_to_call_pattern(proof: Rc) -> Rc { diff --git a/src/v2/stage0/src/v2_compiler_emit.rs b/src/v2/stage0/src/v2_compiler_emit.rs index ec2c5bec4b6..74804a2f808 100644 --- a/src/v2/stage0/src/v2_compiler_emit.rs +++ b/src/v2/stage0/src/v2_compiler_emit.rs @@ -35,7 +35,7 @@ pub use crate::v2_compiler_infer::InferScope; pub use crate::v2_compiler_infer::{build_params_scope, extend_scope}; pub use crate::v2_compiler_infer_emit_info::{EmitGraphInfo, TypeSummary}; pub use crate::v2_compiler_infer_env::authored_name; -pub use crate::v2_compiler_infer_env::{TypeBinding, TypeEnv}; +pub use crate::v2_compiler_infer_env::{TypeBinding, TypeDeclBinding, TypeEnv}; pub use crate::v2_compiler_infer_items::{ItemInfo, ResolvedGraph, TypedModule}; pub use crate::v2_compiler_infer_service::{ extract_typed_service_name, is_typed_service_call_receiver, @@ -108,9 +108,9 @@ pub use crate::v2_std_core::{ unaryop_operand, with_required_cardinality, }; pub use crate::v2_std_core::{ - Cardinality, Connective, DeclaredFuncSig, ErrorNode, ExprData, FieldAccessStyle, FieldSummary, - InferredNode, MatchPattern, MethodSemantics, NewlineIndex, Node, StringPart, TextFile, - UnaryOpKind, VarBindingKind, + BindingId, Cardinality, Connective, DeclaredFuncSig, ErrorNode, ExprData, FieldAccessStyle, + FieldSummary, InferredNode, MatchPattern, MethodSemantics, NewlineIndex, Node, StringPart, + TextFile, UnaryOpKind, VarBindingKind, }; use crate::NonEmptyBTreeSet; use crate::NonEmptyVec; @@ -568,6 +568,9 @@ pub fn empty_emit_scope() -> Rc { Rc::new(InferScope { type_env: Rc::new(TypeEnv { bindings: v2_rt::rc_empty_map::>(), + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: v2_rt::rc_empty_map::>(), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: v2_rt::rc_empty_map::(), inductive_fields: v2_rt::rc_empty_map::>>>(), @@ -578,6 +581,7 @@ pub fn empty_emit_scope() -> Rc { signatures: v2_rt::rc_empty_map::>(), }), locals: v2_rt::rc_empty_map::>(), + variant_collisions: v2_rt::rc_empty_map::>(), match_bound_names: v2_rt::rc_empty_map::(), module_name: "".to_string(), service_registry: v2_rt::rc_empty_map::>>>(), @@ -591,6 +595,7 @@ pub fn module_emit_scope(typed_module: Rc) -> Rc { type_env: typed_module.type_env.clone(), func_env: typed_module.func_env.clone(), locals: v2_rt::rc_empty_map::>(), + variant_collisions: v2_rt::rc_empty_map::>(), match_bound_names: v2_rt::rc_empty_map::(), module_name: authored_name_at( typed_module.type_env.clone().source_indices.clone(), diff --git a/src/v2/stage0/src/v2_compiler_emit_rust.rs b/src/v2/stage0/src/v2_compiler_emit_rust.rs index ec4e36dd359..bf420438127 100644 --- a/src/v2/stage0/src/v2_compiler_emit_rust.rs +++ b/src/v2/stage0/src/v2_compiler_emit_rust.rs @@ -575,6 +575,7 @@ pub fn type_variable_node(id: String) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -690,6 +691,10 @@ pub fn rust_nominal_identity_carrier_shape_eligible( && (n.connective.clone() == Connective::NoConnective)) } +pub fn rust_binding_id_opaque_newtype_bridge(name: String) -> bool { + (name.as_str() == "BindingId".to_string().as_str()) +} + pub fn rust_diff_id_ord_carrier_shape_eligible( name: String, children: Rc>>, @@ -6328,6 +6333,9 @@ pub fn emit_struct_from_children( emit_info: Rc, ) -> String { { + if rust_binding_id_opaque_newtype_bridge(name.clone()) { + return v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat(v2_rt::concat("#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]\n".to_string(), rust_visibility_prefix()), rust_items().struct_keyword.clone()), " BindingId(i64);\n\n".to_string()), "impl BindingId {\n".to_string()), " pub(crate) fn mint(value: i64) -> Self { BindingId(value) }\n".to_string()), "}".to_string()); + } let has_fn_fields = match v2_rt::map_get(&emit_info.type_summaries.clone(), name.clone()) { Some(ts) => ts.has_fn_fields.clone(), None => false, @@ -13797,11 +13805,24 @@ pub fn emit_rust_generic_method_call( ) -> String { { let function_name = method_name; - if rust_receiver_has_callable_method_field( + let receiver_type = resolved_type(receiver.clone()); + let receiver_type_name = authored_name_at( + scope.type_env.clone().source_indices.clone(), + receiver_type.clone(), + ); + let runtime_container_method = + (v2_rt::map_contains_key(&rt_functions(), function_name.clone()) + && (is_container_type(receiver_type_name) + || node_is_keyed_collection( + receiver_type.clone(), + scope.type_env.clone().source_indices.clone(), + ))); + if (rust_receiver_has_callable_method_field( receiver.clone(), function_name.clone(), scope.clone(), - ) { + ) && !runtime_container_method) + { { let recv_str = emit_typed_expr_base( receiver.clone(), @@ -15417,6 +15438,42 @@ pub fn emit_typed_record_lit( } Some(tn) => { let si = scope.type_env.clone().source_indices.clone(); + if rust_binding_id_opaque_newtype_bridge(tn.clone()) { + match Rc::new({ + let mut __result = Vec::new(); + for f in fields.clone().iter().cloned() { + if (field_init_node_name_at(f.clone(), si.clone()).as_str() + == "value".to_string().as_str()) + { + __result.push(f); + } + } + __result + }) + .first() + .cloned() + { + Some(f) => { + let inner = emit_typed_expr( + field_init_node_value(f.clone()), + registry.clone(), + scope.clone(), + depth.clone(), + shared_types.clone(), + emit_info.clone(), + 1024, + ); + return v2_rt::concat( + v2_rt::concat("BindingId::mint(".to_string(), inner.clone()), + ")".to_string(), + ); + } + None => { + return "compile_error!(\"BindingId literal missing value\")" + .to_string() + } + } + } let context_lookup = contextual_variant_parent( tn.clone(), parent_enum.clone(), @@ -15483,7 +15540,7 @@ pub fn emit_typed_record_lit( 1024, ); v2_rt::concat( - v2_rt::concat("Some(".to_string(), inner), + v2_rt::concat("Some(".to_string(), inner.clone()), ")".to_string(), ) } diff --git a/src/v2/stage0/src/v2_compiler_infer.rs b/src/v2/stage0/src/v2_compiler_infer.rs index fb1e6af53e5..97a25c66252 100644 --- a/src/v2/stage0/src/v2_compiler_infer.rs +++ b/src/v2/stage0/src/v2_compiler_infer.rs @@ -30,8 +30,10 @@ use crate::std_termination::PositiveDescentAmount::OneStep; pub use crate::std_termination::{ positive_descent_amount_from_positive_int, proportional_divisor_from_int_at_least_two, }; -pub use crate::std_types::container_param_name; pub use crate::std_types::SourceSpan; +pub use crate::std_types::{ + container_param_name, container_template_algebra, is_kernel_type, kernel_type_set, +}; pub use crate::v2_compiler_infer_access::AccessCheckResultNode; pub use crate::v2_compiler_infer_access::{check_index_access_node, check_slice_access_node}; pub use crate::v2_compiler_infer_cycle::detect_type_cycles_kahn; @@ -44,11 +46,14 @@ pub use crate::v2_compiler_infer_emit_info::{ EmitGraphInfo, EmitInfoBuildState, TypeRepr, TypeSummary, }; pub use crate::v2_compiler_infer_env::{ - inductive_fields_for, inductive_fields_list_to_map, is_recursive_type, - is_recursive_type_by_name, lookup_type, lookup_type_by_name, lookup_type_for, merge_envs, - merge_inductive_fields, put_inductive_field, put_inductive_field_cross, + alloc_binding_id, empty_binding_id_allocator, inductive_fields_for, + inductive_fields_list_to_map, is_recursive_type, is_recursive_type_by_name, lookup_type, + lookup_type_by_name, lookup_type_for, merge_envs, merge_inductive_fields, node_has_binding_id, + put_inductive_field, put_inductive_field_cross, +}; +pub use crate::v2_compiler_infer_env::{ + BindingIdAllocator, TypeBinding, TypeDeclAuthority, TypeDeclBinding, TypeEnv, }; -pub use crate::v2_compiler_infer_env::{TypeBinding, TypeEnv}; use crate::v2_compiler_infer_items::ItemKind::{ DataItem, FnItem, FuncItem, OtherItem, ServiceItem, TypeItem, }; @@ -76,8 +81,8 @@ pub use crate::v2_compiler_infer_patterns::{ }; pub use crate::v2_compiler_infer_patterns::{NodeLookupResult, PatternSubject}; pub use crate::v2_compiler_infer_resolve::{ - peel_nominal_alias_identity, preserve_nominal_brand_on_resolve, resolve_item_types, - resolve_node, + peel_nominal_alias_identity, peel_nominal_alias_identity_result, + preserve_nominal_brand_on_resolve, resolve_item_types, resolve_node, }; pub use crate::v2_compiler_infer_resolve::{ItemResult, NodeResolveResult}; pub use crate::v2_compiler_infer_service::{ @@ -90,8 +95,8 @@ pub use crate::v2_compiler_infer_sigs::resolve_func_sigs; pub use crate::v2_compiler_infer_sigs::{ResolveFuncSigsResult, ResolvedFuncEnv, ResolvedFuncSig}; pub use crate::v2_compiler_infer_types::KernelTypeBuild; pub use crate::v2_compiler_infer_types::{ - bare_map_node, bare_set_node, callable_inferred, child_type_node, emit_map_has, - extract_optional_inner_node, for_each_element_type_node, infer_binop_type_node, + bare_map_node, bare_set_node, callable_inferred, canonical_template_name, child_type_node, + emit_map_has, extract_optional_inner_node, for_each_element_type_node, infer_binop_type_node, infer_literal_node, is_declared_container_alias_spelling, is_fully_resolved, make_callable_type, make_container_type, method_receiver_element_node, node_is_collection, node_is_element_collection, node_is_keyed_collection, node_is_set_collection, @@ -138,22 +143,23 @@ pub use crate::v2_std_core::{ foreach_body, foreach_collection, foreach_variable_at, has_child_named, has_inferred, if_condition, if_else_branch, if_then_branch, import_is_all, index_base, index_expr, int_type, intern, intern_str, is_child_accessor_in_model, is_compiler_error, is_container_type, - is_error_diagnostic, is_kernel_type, is_property_contraction, is_tree_size_reducing, - kernel_type_set, lambda_body, lambda_param_names_at, let_binding_name_at, let_body, let_value, - local_transport_node, make_arg_node, make_arm_node, make_error_node, make_expr_error_node, - make_expr_node, make_field_binding_node, make_field_init_node, make_interp_part_node, - make_named_expr_node, make_param_node, make_span, make_text_part_node, make_transport_node, - map_children, match_arm_nodes, match_scrutinee, method_arg_nodes, method_receiver, - module_imports, module_items, module_node, no_span, node_name_span, none_type, - param_node_name_at, param_node_type_expr, record_lit_type_name_at, resource_use_name_at, - resource_use_resource, return_value, slice_base, slice_end, slice_start, string_type, - unaryop_operand, unit_type, with_optional_cardinality, with_required_cardinality, + is_error_diagnostic, is_property_contraction, is_tree_size_reducing, lambda_body, + lambda_param_names_at, let_binding_name_at, let_body, let_value, local_transport_node, + make_arg_node, make_arm_node, make_error_node, make_expr_error_node, make_expr_node, + make_field_binding_node, make_field_init_node, make_interp_part_node, make_named_expr_node, + make_param_node, make_span, make_text_part_node, make_transport_node, map_children, + match_arm_nodes, match_scrutinee, method_arg_nodes, method_receiver, module_imports, + module_items, module_node, no_span, node_name_span, node_with_binding_id, + node_with_preserved_binding_id, none_type, param_node_name_at, param_node_type_expr, + record_lit_type_name_at, resource_use_name_at, resource_use_resource, return_value, slice_base, + slice_end, slice_start, string_type, unaryop_operand, unit_type, variant_node_fields, + with_optional_cardinality, with_required_cardinality, }; pub use crate::v2_std_core::{ - CallSemantics, Cardinality, CompilerDiagnostic, Connective, DeclaredFuncEnv, DeclaredFuncSig, - ErrorNode, ExprData, ExprErrorKind, FieldAccessStyle, FieldSummary, FieldValueShape, - InferredNode, InternTable, MatchPattern, MethodSemantics, NewlineIndex, Node, StringPart, - UnaryOpKind, VarBindingKind, + BindingId, CallSemantics, Cardinality, CompilerDiagnostic, Connective, DeclaredFuncEnv, + DeclaredFuncSig, ErrorNode, ExprData, ExprErrorKind, FieldAccessStyle, FieldSummary, + FieldValueShape, InferredNode, InternTable, MatchPattern, MethodSemantics, NewlineIndex, Node, + StringPart, UnaryOpKind, VarBindingKind, }; use crate::NonEmptyBTreeSet; use crate::NonEmptyVec; @@ -183,13 +189,36 @@ pub struct ModuleContext { pub svc_registry: Rc>>>>, pub locals: Rc>>, pub item_registry: Rc>>, + pub variant_collisions: Rc>>, pub diagnostics: Rc>>, } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct VariantFoldState { pub locals: Rc>>, - pub collision_errors: Rc>>, + pub collisions: Rc>>, +} + +pub fn is_bootstrap_duplicate_variant_name(name: String) -> bool { + ((((name.clone().as_str() == "Rust".to_string().as_str()) + || (name.clone().as_str() == "Go".to_string().as_str())) + || (name.clone().as_str() == "TreeSize".to_string().as_str())) + || (name.clone().as_str() == "Bits32".to_string().as_str())) +} + +pub fn same_canonical_container_variant_parent( + left: Rc, + right: Rc, + source_indices: Rc>>, +) -> bool { + { + let left_name = canonical_template_name(left.clone(), source_indices.clone()); + let right_name = canonical_template_name(right.clone(), source_indices.clone()); + let same_name = (left_name.as_str() == right_name.as_str()); + (((left.connective.clone() == Connective::Disj) + && (right.connective.clone() == Connective::Disj)) + && same_name) + } } #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] @@ -197,6 +226,7 @@ pub struct InferScope { pub type_env: Rc, pub func_env: Rc, pub locals: Rc>>, + pub variant_collisions: Rc>>, pub match_bound_names: Rc>, pub module_name: String, pub service_registry: Rc>>>>, @@ -313,6 +343,7 @@ pub struct FieldInferResult { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct BuildTypeEnvResult { pub env: Rc, + pub allocator: BindingIdAllocator, pub diagnostics: Rc>>, } @@ -380,21 +411,45 @@ pub fn merge_scope_from_imports( |acc: Rc>>, rsig: Rc| { let sig_key = rsig.name.clone(); - let sig_params = rsig.params.clone(); - let sig_rt = rsig.inferred.clone(); - let sig_async = rsig.is_async.clone(); - v2_rt::rc_map_insert( - acc, - sig_key.clone(), - Rc::new(DeclaredFuncSig { - name: sig_key.clone(), - params: sig_params.clone(), - inferred: Some(sig_rt.clone()), - is_async: sig_async.clone(), - output_provenance: rsig.output_provenance.clone(), - variant_provenance: rsig.variant_provenance.clone(), - }), - ) + if (import_allows_binding_name(imp.clone(), sig_key.clone()) == false) { + acc.clone() + } else { + { + let sig_params = Rc::new({ + let mut __result = Vec::new(); + for p in rsig.params.clone().iter().cloned() { + __result.push(stamp_hidden_dependency_refs( + p.clone(), + typed_parent.type_env.clone(), + typed_parent + .type_env + .clone() + .source_indices + .clone(), + )); + } + __result + }); + let sig_rt = stamp_hidden_dependency_refs( + rsig.inferred.clone(), + typed_parent.type_env.clone(), + typed_parent.type_env.clone().source_indices.clone(), + ); + let sig_async = rsig.is_async.clone(); + v2_rt::rc_map_insert( + acc.clone(), + sig_key.clone(), + Rc::new(DeclaredFuncSig { + name: sig_key.clone(), + params: sig_params.clone(), + inferred: Some(sig_rt.clone()), + is_async: sig_async.clone(), + output_provenance: rsig.output_provenance.clone(), + variant_provenance: rsig.variant_provenance.clone(), + }), + ) + } + } }, ); let parent_result = typed_parent.items.clone().iter().cloned().fold( @@ -404,80 +459,78 @@ pub fn merge_scope_from_imports( svc_locals: svc_locals, }), |acc: Rc, titem: Rc| { - if ((titem.transport.clone() != None) - && ((titem.children.clone().len() as i64) > 0)) + let item_name = + authored_name_at(env.source_indices.clone(), titem.clone()); + if (import_allows_binding_name(imp.clone(), item_name.clone()) == false) { - { - let entries = Rc::new({ - let mut __result = Vec::new(); - for c in titem.children.clone().iter().cloned() { - __result.push(Rc::new(OpEntry { - name: authored_name_at( - env.source_indices.clone(), - c.clone(), - ), - outputs: inferred_to_outputs( - c.inferred.clone(), - c.span.clone(), - env.source_indices.clone(), - ), - params: c.params.clone(), - })); - } - __result - }); - let root = namespace_root_from_properties( - titem.properties.clone(), - authored_name_at(env.source_indices.clone(), titem.clone()), - env.source_indices.clone(), - ); - Rc::new(InferScopeComponents { - func_sigs: acc.func_sigs.clone(), - svc_registry: v2_rt::rc_map_insert( - acc.svc_registry.clone(), - authored_name_at( - env.source_indices.clone(), - titem.clone(), - ), - entries.clone(), - ), - svc_locals: v2_rt::rc_map_insert( - acc.svc_locals.clone(), - root.clone(), - nominal_type_binding(root.clone()), - ), - }) - } + acc.clone() } else { - if (((((titem.body.clone() != None) - && ((titem.params.clone().len() as i64) == 0)) - && (titem.transport.clone() == None)) - && (titem.connective.clone() == Connective::NoConnective)) - && (titem.inferred.clone() != None)) + if ((titem.transport.clone() != None) + && ((titem.children.clone().len() as i64) > 0)) { - Rc::new(InferScopeComponents { - func_sigs: acc.func_sigs.clone(), - svc_registry: acc.svc_registry.clone(), - svc_locals: v2_rt::rc_map_insert( - acc.svc_locals.clone(), - authored_name_at( - env.source_indices.clone(), - titem.clone(), + { + let entries = Rc::new({ + let mut __result = Vec::new(); + for c in titem.children.clone().iter().cloned() { + __result.push(Rc::new(OpEntry { + name: authored_name_at( + env.source_indices.clone(), + c.clone(), + ), + outputs: inferred_to_outputs( + c.inferred.clone(), + c.span.clone(), + env.source_indices.clone(), + ), + params: c.params.clone(), + })); + } + __result + }); + let root = namespace_root_from_properties( + titem.properties.clone(), + item_name.clone(), + env.source_indices.clone(), + ); + Rc::new(InferScopeComponents { + func_sigs: acc.func_sigs.clone(), + svc_registry: v2_rt::rc_map_insert( + acc.svc_registry.clone(), + item_name.clone(), + entries.clone(), ), - Rc::new(TypeBinding { - name: authored_name_at( - env.source_indices.clone(), - titem.clone(), - ), - resolved: resolved_type(titem.clone()), - provenance: Rc::new( - SubValueRelation::SubValueUnknown, - ), - }), - ), - }) + svc_locals: v2_rt::rc_map_insert( + acc.svc_locals.clone(), + root.clone(), + nominal_type_binding(root.clone()), + ), + }) + } } else { - acc.clone() + if (((((titem.body.clone() != None) + && ((titem.params.clone().len() as i64) == 0)) + && (titem.transport.clone() == None)) + && (titem.connective.clone() == Connective::NoConnective)) + && (titem.inferred.clone() != None)) + { + Rc::new(InferScopeComponents { + func_sigs: acc.func_sigs.clone(), + svc_registry: acc.svc_registry.clone(), + svc_locals: v2_rt::rc_map_insert( + acc.svc_locals.clone(), + item_name.clone(), + Rc::new(TypeBinding { + name: item_name.clone(), + resolved: resolved_type(titem.clone()), + provenance: Rc::new( + SubValueRelation::SubValueUnknown, + ), + }), + ), + }) + } else { + acc.clone() + } } } }, @@ -737,6 +790,7 @@ pub fn nominal_ref_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -789,6 +843,16 @@ pub fn ok_infer(texpr: Rc) -> Rc { }) } +pub fn infer_null_literal_node(expected: Option>) -> Rc { + match expected { + Some(exp) => match exp.return_cardinality.clone() { + Cardinality::CardOptional => exp.clone(), + _ => infer_literal_node(Rc::new(LiteralValue::LitNull)), + }, + None => infer_literal_node(Rc::new(LiteralValue::LitNull)), + } +} + pub fn semantic_expr_error_node(message: String, span: Rc) -> Rc { make_expr_error_node(ExprErrorKind::SemanticExprError, message, span) } @@ -797,31 +861,53 @@ pub fn internal_expr_error_node(message: String, span: Rc) -> Rc, + collision: Rc, +) -> Rc { + Rc::new(InferResult { + typed: semantic_expr_error_node( + v2_rt::concat( + v2_rt::concat("ambiguous variant '".to_string(), name), + "'".to_string(), + ), + span, + ), + diagnostics: Rc::new(vec![collision]), + }) +} + pub fn lookup_variant_parent_enum(scope: Rc, name: String) -> Option { - match v2_rt::map_get(&scope.locals.clone(), name.clone()) { - Some(binding) => match lookup_type_for(scope.type_env.clone(), binding.resolved.clone()) { - Some(parent) => { - let is_coproduct = (parent.connective.clone() == Connective::Disj); - if is_coproduct { - if has_child_named( - parent.clone(), - name.clone(), - scope.type_env.clone().source_indices.clone(), - ) { - Some(authored_name_at( - scope.type_env.clone().source_indices.clone(), - binding.resolved.clone(), - )) - } else { - None + match v2_rt::map_get(&scope.variant_collisions.clone(), name.clone()) { + Some(_) => None, + None => match v2_rt::map_get(&scope.locals.clone(), name.clone()) { + Some(binding) => { + match lookup_type_for(scope.type_env.clone(), binding.resolved.clone()) { + Some(parent) => { + let is_coproduct = (parent.connective.clone() == Connective::Disj); + if is_coproduct { + if has_child_named( + parent.clone(), + name.clone(), + scope.type_env.clone().source_indices.clone(), + ) { + Some(authored_name_at( + scope.type_env.clone().source_indices.clone(), + binding.resolved.clone(), + )) + } else { + None + } + } else { + None + } } - } else { - None + None => None, } } None => None, }, - None => None, } } @@ -883,47 +969,100 @@ pub fn rejects_string_for_optional_coproduct_field( let expected_is_optional_coproduct = ((expected.return_cardinality.clone() == Cardinality::CardOptional) && (expected_inner.connective.clone() == Connective::Disj)); - let got_is_string = - (authored_name_at(source_indices, got).as_str() == "String".to_string().as_str()); + let got_is_string = (got.name.clone().as_str() == "String".to_string().as_str()); (expected_is_optional_coproduct && got_is_string) } } +pub fn expected_coproduct_variant( + parent: Rc, + variant_name: String, + source_indices: Rc>>, +) -> Option> { + match parent.connective.clone() { + Connective::Disj => find_child_named(parent.clone(), variant_name, source_indices), + _ => None, + } +} + +pub fn expected_has_coproduct_variant( + expected: Option>, + variant_name: String, + source_indices: Rc>>, +) -> bool { + match expected { + Some(expected_node) => { + match expected_coproduct_variant(expected_node.clone(), variant_name, source_indices) { + Some(_) => true, + None => false, + } + } + None => false, + } +} + pub fn record_lit_expected_fields( type_name: Option, scope: Rc, + expected: Option>, ) -> Rc>> { match type_name { - Some(tn) => match lookup_type_by_name(scope.type_env.clone(), tn.clone()) { - Some(direct) => direct.children.clone(), - None => match lookup_variant_parent_enum(scope.clone(), tn.clone()) { - Some(parent_name) => { - match lookup_type_by_name(scope.type_env.clone(), parent_name.clone()) { - Some(parent) => match Rc::new({ - let mut __result = Vec::new(); - for v in parent.children.clone().iter().cloned() { - if (authored_name_at( - scope.type_env.clone().source_indices.clone(), - v.clone(), - ) - .as_str() - == tn.clone().as_str()) - { - __result.push(v); + Some(tn) => match v2_rt::map_get(&scope.variant_collisions.clone(), tn.clone()) { + Some(_) => Rc::new(vec![]), + None => match lookup_type_by_name(scope.type_env.clone(), tn.clone()) { + Some(direct) => direct.children.clone(), + None => match lookup_variant_parent_enum(scope.clone(), tn.clone()) { + Some(parent_name) => { + match lookup_type_by_name(scope.type_env.clone(), parent_name.clone()) { + Some(parent) => match Rc::new({ + let mut __result = Vec::new(); + for v in parent.children.clone().iter().cloned() { + if (authored_name_at( + scope.type_env.clone().source_indices.clone(), + v.clone(), + ) + .as_str() + == tn.clone().as_str()) + { + __result.push(v); + } } - } - __result - }) - .first() - .cloned() - { + __result + }) + .first() + .cloned() + { + Some(variant) => variant.children.clone(), + None => Rc::new(vec![]), + }, + None => Rc::new(vec![]), + } + } + None => match lookup_coproduct_parent_binding_by_variant( + scope.type_env.clone(), + tn.clone(), + ) { + Some(parent_binding) => match expected_coproduct_variant( + parent_binding.resolved.clone(), + tn.clone(), + scope.type_env.clone().source_indices.clone(), + ) { Some(variant) => variant.children.clone(), None => Rc::new(vec![]), }, - None => Rc::new(vec![]), - } - } - None => Rc::new(vec![]), + None => match expected { + Some(expected_node) => match expected_coproduct_variant( + expected_node.clone(), + tn.clone(), + scope.type_env.clone().source_indices.clone(), + ) { + Some(variant) => variant.children.clone(), + None => Rc::new(vec![]), + }, + None => Rc::new(vec![]), + }, + }, + }, }, }, None => Rc::new(vec![]), @@ -1016,1740 +1155,2561 @@ pub fn type_node_is_callable(n: Rc) -> bool { } pub fn module_skips_direct_call_arg_check(module_name: String) -> bool { - { - let is_v4 = ((v2_rt::string_length(&module_name) >= 3) - && (v2_rt::substring(&module_name, 0, 3).as_str() == "v4.".to_string().as_str())); - let is_compiler_substrate = ((v2_rt::string_length(&module_name) >= 13) - && (v2_rt::substring(&module_name, 0, 13).as_str() - == "v2.compiler.".to_string().as_str())); - (is_v4 || is_compiler_substrate) - } + false } -pub fn nominal_call_arg_brand_mismatch( - formal: Rc, - actual: Rc, +pub fn direct_call_actual_is_none( + actual_expr: Rc, + actual_type: Rc, source_indices: Rc>>, ) -> bool { - { - let formal_name = authored_name_at(source_indices.clone(), formal.clone()); - let actual_name = authored_name_at(source_indices.clone(), actual.clone()); - ((((((((formal.connective.clone() != Connective::Arrow) - && (actual.connective.clone() != Connective::Arrow)) - && (formal_name.clone().as_str() != "".to_string().as_str())) - && (actual_name.clone().as_str() != "".to_string().as_str())) - && (formal_name.clone().as_str() != actual_name.clone().as_str())) - && (structural_carrier_template_name(formal.clone(), source_indices.clone()) - .as_str() - == structural_carrier_template_name(actual.clone(), source_indices.clone()) - .as_str())) - && !is_declared_container_alias_spelling(formal_name.clone())) - && !is_declared_container_alias_spelling(actual_name.clone())) - } + ((authored_name_at(source_indices.clone(), actual_expr).as_str() + == "none".to_string().as_str()) + || (authored_name_at(source_indices.clone(), actual_type).as_str() + == "None".to_string().as_str())) } -pub fn container_element_nominal_brand_mismatch( - formal: Rc, - actual: Rc, - type_env: Rc, - module_name: String, +pub fn direct_call_actual_is_empty_collection( + formal_raw: Rc, + actual_expr: Rc, + actual_type: Rc, source_indices: Rc>>, ) -> bool { - if ((node_is_element_collection(formal.clone(), source_indices.clone()) - && node_is_element_collection(actual.clone(), source_indices.clone())) - && (authored_name_at(source_indices.clone(), formal.clone()).as_str() - == authored_name_at(source_indices.clone(), actual.clone()).as_str())) - { - match formal.children.clone().first().cloned() { - Some(formal_ch) => match actual.children.clone().first().cloned() { - Some(actual_ch) => { - let formal_el = peel_nominal_alias_identity( - child_type_node(formal_ch.clone()), - type_env.clone(), - module_name.clone(), - ); - let actual_el = peel_nominal_alias_identity( - child_type_node(actual_ch.clone()), - type_env.clone(), - module_name.clone(), - ); - nominal_call_arg_brand_mismatch(formal_el, actual_el, source_indices.clone()) - } - None => false, - }, - None => false, - } - } else { - false - } + (((authored_name_at(source_indices.clone(), actual_expr).as_str() + == "Empty".to_string().as_str()) + && node_is_element_collection(formal_raw, source_indices.clone())) + && node_is_element_collection(actual_type, source_indices.clone())) } -pub fn direct_call_arg_type_mismatch( - formal: Rc, - actual: Rc, - type_env: Rc, - module_name: String, +pub fn direct_call_arg_is_typed_deferral( + formal_raw: Rc, + actual_expr: Rc, + actual_type: Rc, source_indices: Rc>>, ) -> bool { - if (type_node_is_callable(formal.clone()) || type_node_is_callable(actual.clone())) { - false - } else { - (nominal_call_arg_brand_mismatch(formal.clone(), actual.clone(), source_indices.clone()) - || container_element_nominal_brand_mismatch( - formal.clone(), - actual.clone(), - type_env, - module_name, - source_indices.clone(), - )) + { + let formal_is_callable = (type_node_is_callable(formal_raw.clone()) + || (authored_name_at(source_indices.clone(), formal_raw.clone()).as_str() + == "Callable".to_string().as_str())); + let actual_is_callable_literal = is_lambda_expr(actual_expr.clone()); + let formal_is_optional = ((formal_raw.return_cardinality.clone() + == Cardinality::CardOptional) + || (authored_name_at(source_indices.clone(), formal_raw.clone()).as_str() + == "Optional".to_string().as_str())); + let actual_is_none = direct_call_actual_is_none( + actual_expr.clone(), + actual_type.clone(), + source_indices.clone(), + ); + let actual_is_empty_collection = direct_call_actual_is_empty_collection( + formal_raw.clone(), + actual_expr.clone(), + actual_type.clone(), + source_indices.clone(), + ); + (((formal_is_callable && actual_is_callable_literal) + || (formal_is_optional && actual_is_none)) + || actual_is_empty_collection) } } -pub fn direct_call_arg_mismatch_diags( - value_params: Rc>>, - typed_args: Rc>>, - call_subst: Rc>>, - type_env: Rc, - module_name: String, -) -> Rc>> { - { - let source_indices = type_env.source_indices.clone(); - Rc::new({ - let mut __result = Vec::new(); - for pair in Rc::new( - value_params - .iter() - .cloned() - .enumerate() - .map(|(i, v)| (i as i64, v)) - .collect::>(), - ) - .iter() - .cloned() - { - __result.extend( - (*{ - let formal_raw = param_node_type_expr(pair.1.clone()); - let formal_subst = substitute_generics( - formal_raw.clone(), - call_subst.clone(), - source_indices.clone(), - ); - let formal = peel_nominal_alias_identity( - formal_subst.clone(), - type_env.clone(), - module_name.clone(), - ); - match typed_args.clone().get(pair.0.clone() as usize).cloned() { - Some(ta) => { - let actual_raw = resolved_type(arg_value(ta.clone())); - let actual = peel_nominal_alias_identity( - actual_raw.clone(), - type_env.clone(), - module_name.clone(), - ); - if direct_call_arg_type_mismatch( - formal.clone(), - actual.clone(), - type_env.clone(), - module_name.clone(), - source_indices.clone(), - ) { - Rc::new(vec![type_mismatch_error( - node_type_shape(formal.clone(), source_indices.clone()), - node_type_shape(actual.clone(), source_indices.clone()), - arg_value(ta.clone()).span.clone(), - module_name.clone(), - )]) - } else { - Rc::new(vec![]) - } - } - None => Rc::new(vec![]), - } - }) - .iter() - .cloned(), - ); +pub fn node_contains_type_variable(n: Rc) -> bool { + stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { + let inferred_has_type_variable = match n.inferred.clone().as_deref().cloned() { + Some(InferredNode::TypeVariable { id: _, .. }) => true, + Some(InferredNode::Resolved { node: rt, .. }) => { + node_contains_type_variable(rt.clone()) } - __result + _ => false, + }; + ((inferred_has_type_variable || { + let mut __found = false; + for ch in n.children.clone().iter().cloned() { + if node_contains_type_variable(ch.clone()) { + __found = true; + break; + } + } + __found + }) || { + let mut __found = false; + for p in n.params.clone().iter().cloned() { + if node_contains_type_variable(p.clone()) { + __found = true; + break; + } + } + __found + }) + }) +} + +pub fn node_contains_generic_name( + n: Rc, + generic_names: Rc>, + source_indices: Rc>>, +) -> bool { + stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { + let n_name = authored_name_at(source_indices.clone(), n.clone()); + let is_generic_leaf = ((((n.connective.clone() == Connective::NoConnective) + && ((n.children.clone().len() as i64) == 0)) + && ((n.params.clone().len() as i64) == 0)) + && { + let mut __found = false; + for g in generic_names.clone().iter().cloned() { + if (g.clone().as_str() == n_name.clone().as_str()) { + __found = true; + break; + } + } + __found + }); + (((is_generic_leaf || { + let mut __found = false; + for ch in n.children.clone().iter().cloned() { + if node_contains_generic_name( + ch.clone(), + generic_names.clone(), + source_indices.clone(), + ) { + __found = true; + break; + } + } + __found + }) || { + let mut __found = false; + for p in n.params.clone().iter().cloned() { + if node_contains_generic_name( + p.clone(), + generic_names.clone(), + source_indices.clone(), + ) { + __found = true; + break; + } + } + __found + }) || match n.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: rt, .. }) => node_contains_generic_name( + rt.clone(), + generic_names.clone(), + source_indices.clone(), + ), + _ => false, }) + }) +} + +pub fn direct_call_arg_decl_identity(n: Rc, env: Rc) -> Rc { + match n.binding_id.clone() { + Some(_) => n.clone(), + None => match lookup_type_for(env, n.clone()) { + Some(resolved) => { + let resolved_with_cardinality = with_optional_cardinality(resolved.clone()); + match n.return_cardinality.clone() { + Cardinality::CardOptional => resolved_with_cardinality, + _ => resolved.clone(), + } + } + None => n.clone(), + }, } } -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct Tier2bBt { - pub bt: Rc, - pub kernel_diags: Rc>>, +pub fn direct_call_node_binding(env: Rc, n: Rc) -> Option> { + match n.binding_id.clone() { + Some(binding_id) => match v2_rt::map_get(&env.decl_registry.clone(), binding_id.clone()) { + Some(decl) => match v2_rt::map_get(&env.bindings.clone(), decl.binding_key.clone()) { + Some(binding) => { + if node_has_binding_id(binding.resolved.clone(), binding_id.clone()) { + Some(binding.clone()) + } else { + v2_rt::map_get(&env.carrier_bindings.clone(), binding_id.clone()) + } + } + None => v2_rt::map_get(&env.carrier_bindings.clone(), binding_id.clone()), + }, + None => v2_rt::map_get(&env.carrier_bindings.clone(), binding_id.clone()), + }, + None => None, + } } -pub fn infer_tier2b_builtin_with_kernel_diags( - func_name: String, - typed_args: Rc>>, - scope: Rc, - span: Rc, -) -> Rc { - if ((func_name.clone().as_str() == "lookup".to_string().as_str()) - || (func_name.clone().as_str() == "map_get".to_string().as_str())) +pub fn direct_call_bare_alias_target_name( + binding: Rc, + source_indices: Rc>>, +) -> Option { + match direct_call_bare_alias_target_node(binding) { + Some(target) => Some(authored_name_at(source_indices, target.clone())), + None => None, + } +} + +pub fn direct_call_bare_alias_target_node(binding: Rc) -> Option> { { - Rc::new(Tier2bBt { - bt: match typed_args.clone().first().cloned() { - Some(receiver_arg) => match arg_value(receiver_arg.clone()) - .inferred - .clone() - .as_deref() - .cloned() - { - Some(InferredNode::Resolved { - node: receiver_type, - .. - }) => { - match map_value_type_in_env(receiver_type.clone(), scope.type_env.clone()) { - Some(value_type) => { - if (func_name.clone().as_str() == "lookup".to_string().as_str()) { - witness_of_element(value_type.clone()) - } else { - with_optional_cardinality(value_type.clone()) + let resolved = binding.resolved.clone(); + if (((resolved.connective.clone() == Connective::NoConnective) + && ((resolved.children.clone().len() as i64) == 0)) + && ((resolved.params.clone().len() as i64) == 0)) + { + match resolved.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: target, .. }) => { + let declared_or_structural_target = ((target.binding_id.clone() != None) + || (target.connective.clone() != Connective::NoConnective)); + if declared_or_structural_target { + Some(target.clone()) + } else { + None + } + } + _ => None, + } + } else { + None + } + } +} + +pub fn direct_call_target_matches_alias_target( + env: Rc, + target_node: Rc, + alias_target: String, +) -> bool { + match target_node.binding_id.clone() { + Some(binding_id) => match v2_rt::map_get(&env.decl_registry.clone(), binding_id.clone()) { + Some(decl) => (decl.name.clone().as_str() == alias_target.as_str()), + None => { + (authored_name_at(env.source_indices.clone(), target_node.clone()).as_str() + == alias_target.as_str()) + } + }, + None => { + (authored_name_at(env.source_indices.clone(), target_node.clone()).as_str() + == alias_target.as_str()) + } + } +} + +pub fn direct_call_target_matches_alias_target_node( + env: Rc, + target_node: Rc, + alias_target_node: Rc, +) -> bool { + { + let alias_target_name = + authored_name_at(env.source_indices.clone(), alias_target_node.clone()); + match alias_target_node.binding_id.clone() { + Some(alias_target_binding_id) => match target_node.binding_id.clone() { + Some(target_binding_id) => { + (target_binding_id.clone() == alias_target_binding_id.clone()) + } + None => false, + }, + None => { + ((alias_target_name.clone().as_str() != "".to_string().as_str()) + && direct_call_target_matches_alias_target( + env.clone(), + target_node, + alias_target_name.clone(), + )) + } + } + } +} + +pub fn direct_call_carrier_transparent_alias_to( + env: Rc, + alias_node: Rc, + target_node: Rc, +) -> bool { + match alias_node.binding_id.clone() { + Some(alias_binding_id) => { + match v2_rt::map_get(&env.carrier_bindings.clone(), alias_binding_id.clone()) { + Some(carrier) => { + let carrier_target = match direct_call_bare_alias_target_node(carrier.clone()) { + Some(target) => target.clone(), + None => { + let carrier_is_structural_shell = + (((carrier.resolved.clone().connective.clone() + != Connective::NoConnective) + || ((carrier.resolved.clone().children.clone().len() as i64) + > 0)) + || ((carrier.resolved.clone().params.clone().len() as i64) + > 0)); + let carrier_has_alias_id = + match carrier.resolved.clone().binding_id.clone() { + Some(carrier_binding_id) => { + (carrier_binding_id.clone() == alias_binding_id.clone()) + } + None => false, + }; + let carrier_name = authored_name_at( + env.source_indices.clone(), + carrier.resolved.clone(), + ); + if ((carrier_is_structural_shell && carrier_has_alias_id) + && (carrier.name.clone().as_str() != carrier_name.clone().as_str())) + { + match lookup_type_by_name(env.clone(), carrier_name.clone()) { + Some(resolved_target) => resolved_target.clone(), + None => carrier.resolved.clone(), } + } else { + carrier.resolved.clone() } - None => resolve_builtin_call_type(func_name.clone()), } - } - _ => resolve_builtin_call_type(func_name.clone()), - }, - None => resolve_builtin_call_type(func_name.clone()), - }, - kernel_diags: Rc::new(vec![]), - }) - } else { - if (func_name.clone().as_str() == "map_keys".to_string().as_str()) { - match typed_args.clone().first().cloned() { - Some(receiver_arg) => match arg_value(receiver_arg.clone()) - .inferred - .clone() - .as_deref() - .cloned() - { - Some(InferredNode::Resolved { - node: receiver_type, - .. - }) => { - match map_key_type_in_env(receiver_type.clone(), scope.type_env.clone()) { - Some(key_type) => { - let lk = list_kernel_ty_from_element(key_type.clone()); - Rc::new(Tier2bBt { - bt: lk.ty.clone(), - kernel_diags: lk.miss_diags.clone(), + }; + match carrier_target.binding_id.clone() { + Some(carrier_target_binding_id) => { + ((carrier_target_binding_id.clone() != alias_binding_id.clone()) + && match target_node.binding_id.clone() { + Some(target_binding_id) => { + (target_binding_id.clone() + == carrier_target_binding_id.clone()) + } + None => false, }) + } + None => false, + } + } + None => false, + } + } + None => false, + } +} + +pub fn direct_call_transparent_alias_to( + env: Rc, + alias_node: Rc, + target_node: Rc, +) -> bool { + { + let target_name = authored_name_at(env.source_indices.clone(), target_node.clone()); + if direct_call_carrier_transparent_alias_to( + env.clone(), + alias_node.clone(), + target_node.clone(), + ) { + true + } else { + match direct_call_node_binding(env.clone(), alias_node.clone()) { + Some(binding) => match direct_call_bare_alias_target_node(binding.clone()) { + Some(alias_target_node) => direct_call_target_matches_alias_target_node( + env.clone(), + target_node.clone(), + alias_target_node.clone(), + ), + None => { + let resolved_name = + authored_name_at(env.source_indices.clone(), binding.resolved.clone()); + let alias_decl_name = match alias_node.binding_id.clone() { + Some(binding_id) => { + match v2_rt::map_get(&env.decl_registry.clone(), binding_id.clone()) + { + Some(decl) => decl.name.clone(), + None => binding.name.clone(), + } } - None => Rc::new(Tier2bBt { - bt: resolve_builtin_call_type(func_name.clone()), - kernel_diags: Rc::new(vec![]), - }), + None => binding.name.clone(), + }; + let declared_or_structural_target = + ((binding.resolved.clone().binding_id.clone() != None) + || (binding.resolved.clone().connective.clone() + != Connective::NoConnective)); + (((alias_decl_name.as_str() != resolved_name.as_str()) + && declared_or_structural_target) + && direct_call_target_matches_alias_target_node( + env.clone(), + target_node.clone(), + binding.resolved.clone(), + )) + } + }, + None => match alias_node.binding_id.clone() { + Some(binding_id) => { + match v2_rt::map_get(&env.decl_registry.clone(), binding_id.clone()) { + Some(decl) => match v2_rt::map_get( + &env.bindings.clone(), + decl.binding_key.clone(), + ) { + Some(raw_binding) => { + let raw_resolved_name = authored_name_at( + env.source_indices.clone(), + raw_binding.resolved.clone(), + ); + let declared_or_structural_target = + ((raw_binding.resolved.clone().binding_id.clone() != None) + || (raw_binding.resolved.clone().connective.clone() + != Connective::NoConnective)); + (((decl.name.clone().as_str() != raw_resolved_name.as_str()) + && declared_or_structural_target) + && direct_call_target_matches_alias_target_node( + env.clone(), + target_node.clone(), + raw_binding.resolved.clone(), + )) + } + None => false, + }, + None => false, } } - _ => Rc::new(Tier2bBt { - bt: resolve_builtin_call_type(func_name.clone()), - kernel_diags: Rc::new(vec![]), - }), + None => false, }, - None => Rc::new(Tier2bBt { - bt: resolve_builtin_call_type(func_name.clone()), - kernel_diags: Rc::new(vec![]), - }), } - } else { - if (func_name.clone().as_str() == "map_values".to_string().as_str()) { - match typed_args.clone().first().cloned() { - Some(receiver_arg) => match arg_value(receiver_arg.clone()) - .inferred - .clone() - .as_deref() - .cloned() - { - Some(InferredNode::Resolved { - node: receiver_type, - .. - }) => match map_value_type_in_env( - receiver_type.clone(), - scope.type_env.clone(), - ) { - Some(value_type) => { - let lv = list_kernel_ty_from_element(value_type.clone()); - Rc::new(Tier2bBt { - bt: lv.ty.clone(), - kernel_diags: lv.miss_diags.clone(), - }) - } - None => Rc::new(Tier2bBt { - bt: resolve_builtin_call_type(func_name.clone()), - kernel_diags: Rc::new(vec![]), - }), - }, - _ => Rc::new(Tier2bBt { - bt: resolve_builtin_call_type(func_name.clone()), - kernel_diags: Rc::new(vec![]), - }), - }, - None => Rc::new(Tier2bBt { - bt: resolve_builtin_call_type(func_name.clone()), - kernel_diags: Rc::new(vec![]), - }), - } - } else { - if (((func_name.clone().as_str() == "set_insert".to_string().as_str()) - || (func_name.clone().as_str() == "set_union".to_string().as_str())) - || (func_name.clone().as_str() == "set_contains".to_string().as_str())) - { - { - let operand_elem = if ((func_name.clone().as_str() - == "set_insert".to_string().as_str()) - || (func_name.clone().as_str() == "set_contains".to_string().as_str())) - { - match typed_args.clone().get(1 as usize).cloned() { - Some(insert_arg) => match arg_value(insert_arg.clone()) - .inferred - .clone() - .as_deref() - .cloned() - { - Some(InferredNode::Resolved { node: elem, .. }) => { - Some(elem.clone()) + } + } +} + +pub fn direct_call_decl_registry_transparent_alias_to( + env: Rc, + alias_node: Rc, + target_node: Rc, +) -> bool { + { + let target_name = authored_name_at(env.source_indices.clone(), target_node.clone()); + match alias_node.binding_id.clone() { + Some(binding_id) => { + match v2_rt::map_get(&env.decl_registry.clone(), binding_id.clone()) { + Some(decl) => { + match v2_rt::map_get(&env.bindings.clone(), decl.binding_key.clone()) { + Some(raw_binding) => { + match direct_call_bare_alias_target_node(raw_binding.clone()) { + Some(alias_target_node) => { + (((decl.name.clone().as_str() != target_name.as_str()) + && (raw_binding.name.clone().as_str() + == decl.name.clone().as_str())) + && direct_call_target_matches_alias_target_node( + env.clone(), + target_node.clone(), + alias_target_node.clone(), + )) } - _ => None, - }, - None => None, - } - } else { - match typed_args.clone().get(1 as usize).cloned() { - Some(other_arg) => match arg_value(other_arg.clone()) - .inferred - .clone() - .as_deref() - .cloned() - { - Some(InferredNode::Resolved { - node: other_type, .. - }) => match set_element_type_in_env( - other_type.clone(), - scope.type_env.clone(), - ) { - Some(elem_slot) => Some(child_type_node(elem_slot.clone())), - None => None, - }, - _ => None, - }, - None => None, - } - }; - let recv_is_set = match typed_args.clone().first().cloned() { - Some(receiver_arg) => { - set_builtin_receiver_is_set(receiver_arg.clone(), scope.clone()) - } - None => false, - }; - let union_other_bad = - if (func_name.clone().as_str() == "set_union".to_string().as_str()) { - match typed_args.clone().get(1 as usize).cloned() { - Some(other_arg) => set_union_other_operand_is_resolved_non_set( - other_arg.clone(), - scope.clone(), - ), None => false, } - } else { - false - }; - let recv_elem = match typed_args.clone().first().cloned() { - Some(receiver_arg) => match arg_value(receiver_arg.clone()) - .inferred - .clone() - .as_deref() - .cloned() - { - Some(InferredNode::Resolved { - node: receiver_type, - .. - }) => set_element_type_from_receiver( - receiver_type.clone(), - scope.clone(), - ), - _ => None, - }, - None => None, - }; - let elem_mismatch = match recv_elem.clone() { - Some(re) => match operand_elem.clone() { - Some(oe) => set_element_types_mismatch( - re.clone(), - oe.clone(), - scope.type_env.clone().source_indices.clone(), - ), - None => false, - }, - None => false, - }; - let wrong_receiver_diags = if recv_is_set.clone() { - Rc::new(vec![]) - } else { - Rc::new(vec![inference_error( - v2_rt::concat( - func_name.clone(), - " receiver must be a Set".to_string(), - ), - span.clone(), - scope.module_name.clone(), - )]) - }; - let wrong_union_other_diags = if union_other_bad.clone() { - Rc::new(vec![inference_error( - "set_union second operand must be a Set".to_string(), - span.clone(), - scope.module_name.clone(), - )]) - } else { - Rc::new(vec![]) - }; - let mismatch_diags = if elem_mismatch.clone() { - Rc::new(vec![inference_error( - v2_rt::concat( - func_name.clone(), - " incompatible set element types".to_string(), - ), - span.clone(), - scope.module_name.clone(), - )]) - } else { - Rc::new(vec![]) - }; - let result_bt = if (func_name.clone().as_str() - == "set_contains".to_string().as_str()) - { - if (recv_is_set.clone() && !elem_mismatch.clone()) { - bool_type() - } else { - resolve_builtin_call_type(func_name.clone()) - } - } else { - match typed_args.clone().first().cloned() { - Some(receiver_arg) => { - if ((recv_is_set.clone() && !elem_mismatch.clone()) - && !union_other_bad.clone()) - { - match arg_value(receiver_arg.clone()) - .inferred - .clone() - .as_deref() - .cloned() - { - Some(InferredNode::Resolved { - node: receiver_type, - .. - }) => match recv_elem.clone() { - Some(_) => receiver_type.clone(), - None => match operand_elem.clone() { - Some(element) => { - set_kernel_ty_from_element(element.clone()) - .ty - .clone() - } - None => { - resolve_builtin_call_type(func_name.clone()) - } - }, - }, - _ => resolve_builtin_call_type(func_name.clone()), - } - } else { - resolve_builtin_call_type(func_name.clone()) - } - } - None => resolve_builtin_call_type(func_name.clone()), - } - }; - let build_diags = if (func_name.clone().as_str() - == "set_contains".to_string().as_str()) - { - Rc::new(vec![]) - } else { - match operand_elem.clone() { - Some(element) => { - if ((recv_is_set.clone() && !elem_mismatch.clone()) - && !union_other_bad.clone()) - { - set_kernel_ty_from_element(element.clone()) - .miss_diags - .clone() - } else { - Rc::new(vec![]) - } - } - None => Rc::new(vec![]), } - }; - Rc::new(Tier2bBt { - bt: result_bt, - kernel_diags: v2_rt::concat( - wrong_receiver_diags, - v2_rt::concat( - wrong_union_other_diags, - v2_rt::concat(mismatch_diags, build_diags), - ), - ), - }) + None => false, + } } - } else { - Rc::new(Tier2bBt { - bt: resolve_builtin_call_type(func_name.clone()), - kernel_diags: Rc::new(vec![]), - }) + None => false, } } + None => false, } } } -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct MethodPipeFallback { - pub result_ty: Rc, - pub kernel_diags: Rc>>, -} - -pub fn method_pipe_map_keys_values_fallback( - recv_rt: Rc, - method_name: String, - scope: Rc, - span: Rc, -) -> Rc { - if (method_name.clone().as_str() == "map_keys".to_string().as_str()) { - match map_key_type_in_env(recv_rt.clone(), scope.type_env.clone()) { - Some(key_type) => { - let lk = list_kernel_ty_from_element(key_type.clone()); - Rc::new(MethodPipeFallback { - result_ty: lk.ty.clone(), - kernel_diags: lk.miss_diags.clone(), - }) - } - None => Rc::new(MethodPipeFallback { - result_ty: recv_rt.clone(), - kernel_diags: Rc::new(vec![]), - }), - } - } else { - if (method_name.clone().as_str() == "map_values".to_string().as_str()) { - match map_value_type_in_env(recv_rt.clone(), scope.type_env.clone()) { - Some(value_type) => { - let lv = list_kernel_ty_from_element(value_type.clone()); - Rc::new(MethodPipeFallback { - result_ty: lv.ty.clone(), - kernel_diags: lv.miss_diags.clone(), - }) +pub fn direct_call_transparent_alias_pair( + env: Rc, + left: Rc, + right: Rc, + source_indices: Rc>>, +) -> bool { + (((direct_call_transparent_alias_to(env.clone(), left.clone(), right.clone()) + || direct_call_transparent_alias_to(env.clone(), right.clone(), left.clone())) + || direct_call_decl_registry_transparent_alias_to( + env.clone(), + left.clone(), + right.clone(), + )) + || direct_call_decl_registry_transparent_alias_to(env.clone(), right.clone(), left.clone())) +} + +pub fn direct_call_decl_identity_mismatch( + formal_identity: Rc, + actual_identity: Rc, + formal: Rc, + actual: Rc, + env: Rc, + source_indices: Rc>>, +) -> bool { + { + let formal_container = node_is_element_collection(formal.clone(), source_indices.clone()); + let actual_container = node_is_element_collection(actual.clone(), source_indices.clone()); + let same_structural_carrier = + (structural_carrier_template_name(formal.clone(), source_indices.clone()).as_str() + == structural_carrier_template_name(actual.clone(), source_indices.clone()) + .as_str()); + match formal_identity.binding_id.clone() { + Some(formal_binding_id) => match actual_identity.binding_id.clone() { + Some(actual_binding_id) => { + (((((formal_binding_id.clone() != actual_binding_id.clone()) + && same_structural_carrier) + && !formal_container) + && !actual_container) + && !direct_call_transparent_alias_pair( + env, + formal_identity.clone(), + actual_identity.clone(), + source_indices.clone(), + )) } - None => Rc::new(MethodPipeFallback { - result_ty: recv_rt.clone(), - kernel_diags: Rc::new(vec![]), - }), - } - } else { - Rc::new(MethodPipeFallback { - result_ty: recv_rt.clone(), - kernel_diags: Rc::new(vec![]), - }) + None => false, + }, + None => false, } } } -pub fn categorized_error( - message: String, - span: Rc, - module_name: String, - category: String, -) -> Rc { - make_error_node( - Rc::new(CompilerDiagnostic::InternalError { - message: message, - span: span, - }), - module_name, - ) +pub fn nominal_call_arg_brand_mismatch( + formal: Rc, + actual: Rc, + source_indices: Rc>>, +) -> bool { + { + let formal_name = authored_name_at(source_indices.clone(), formal.clone()); + let actual_name = authored_name_at(source_indices.clone(), actual.clone()); + let distinct_brand = match formal.binding_id.clone() { + Some(formal_binding_id) => match actual.binding_id.clone() { + Some(actual_binding_id) => (formal_binding_id.clone() != actual_binding_id.clone()), + None => (formal_name.clone().as_str() != actual_name.clone().as_str()), + }, + None => (formal_name.clone().as_str() != actual_name.clone().as_str()), + }; + ((((((((formal.connective.clone() != Connective::Arrow) + && (actual.connective.clone() != Connective::Arrow)) + && (formal_name.clone().as_str() != "".to_string().as_str())) + && (actual_name.clone().as_str() != "".to_string().as_str())) + && distinct_brand) + && (structural_carrier_template_name(formal.clone(), source_indices.clone()) + .as_str() + == structural_carrier_template_name(actual.clone(), source_indices.clone()) + .as_str())) + && !is_declared_container_alias_spelling(formal_name.clone())) + && !is_declared_container_alias_spelling(actual_name.clone())) + } } -pub fn validate_cast( - source_inferred: Option>, - target_name: String, - span: Rc, - source_indices: Rc>>, +pub fn container_element_nominal_brand_mismatch( + formal: Rc, + actual: Rc, + type_env: Rc, module_name: String, -) -> Option> { - match source_inferred.as_deref().cloned() { - Some(InferredNode::Resolved { node: src_node, .. }) => { - let source_name = authored_name_at(source_indices, src_node.clone()); - if (source_name.clone().as_str() == target_name.clone().as_str()) { - None - } else { - if !is_dag_cast_domain_type(source_name.clone()) { - None - } else { - if !is_dag_cast_domain_type(target_name.clone()) { - None - } else { - if dag_can_cast(source_name.clone(), target_name.clone()) { - None - } else { - { - let msg = v2_rt::concat( - v2_rt::concat( - v2_rt::concat( - "invalid cast: ".to_string(), - source_name.clone(), - ), - " as ".to_string(), - ), - target_name.clone(), - ); - let diag = Rc::new(CompilerDiagnostic::InternalError { - message: msg, - span: span, - }); - Some(make_error_node(diag, module_name)) - } - } - } + source_indices: Rc>>, +) -> bool { + if ((node_is_element_collection(formal.clone(), source_indices.clone()) + && node_is_element_collection(actual.clone(), source_indices.clone())) + && (authored_name_at(source_indices.clone(), formal.clone()).as_str() + == authored_name_at(source_indices.clone(), actual.clone()).as_str())) + { + match formal.children.clone().first().cloned() { + Some(formal_ch) => match actual.children.clone().first().cloned() { + Some(actual_ch) => { + let formal_el = peel_nominal_alias_identity( + child_type_node(formal_ch.clone()), + type_env.clone(), + module_name.clone(), + ); + let actual_el = peel_nominal_alias_identity( + child_type_node(actual_ch.clone()), + type_env.clone(), + module_name.clone(), + ); + nominal_call_arg_brand_mismatch(formal_el, actual_el, source_indices.clone()) } - } + None => false, + }, + None => false, } - _ => None, + } else { + false } } -pub fn type_variable_node(id: String) -> Rc { - Rc::new(Node { - name: "".to_string(), - span: make_span(0, 0), - ident_span: None, - children: Rc::new(vec![]), - connective: Connective::NoConnective, - params: Rc::new(vec![]), - inferred: Some(Rc::new(InferredNode::TypeVariable { id: id })), - return_cardinality: Cardinality::Required, - uses: Rc::new(vec![]), - body: None, - transport: None, - properties: Rc::new(vec![]), - type_annotation: None, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }) -} - -pub fn is_type_variable(inferred: Rc) -> bool { - match (*inferred).clone() { - InferredNode::TypeVariable { id: _, .. } => true, - _ => false, +pub fn direct_call_plain_kernel_leaf_mismatch( + formal: Rc, + actual: Rc, + source_indices: Rc>>, +) -> bool { + { + let formal_name = authored_name_at(source_indices.clone(), formal.clone()); + let actual_name = authored_name_at(source_indices.clone(), actual.clone()); + (((((((((((formal.binding_id.clone() == None) + && (actual.binding_id.clone() == None)) + && (formal.connective.clone() == Connective::NoConnective)) + && (actual.connective.clone() == Connective::NoConnective)) + && ((formal.children.clone().len() as i64) == 0)) + && ((actual.children.clone().len() as i64) == 0)) + && (formal.return_cardinality.clone() == Cardinality::Required)) + && (actual.return_cardinality.clone() == Cardinality::Required)) + && is_kernel_type(formal_name.clone())) + && is_kernel_type(actual_name.clone())) + && (formal_name.clone().as_str() != actual_name.clone().as_str())) } } -pub fn inferred_or_error( - result: Option>, - fallback_message: String, - fallback_span: Rc, -) -> Rc { - match result { - Some(inferred) => inferred.clone(), - None => Rc::new(InferredNode::CompilerError { - message: fallback_message, - span: fallback_span, - }), +pub fn direct_call_element_collection_carrier( + n: Rc, + source_indices: Rc>>, +) -> bool { + { + let name = authored_name_at(source_indices.clone(), n.clone()); + let child_count = (n.children.clone().len() as i64); + ((node_is_element_collection(n.clone(), source_indices.clone()) + || is_declared_container_alias_spelling(name)) + && (child_count == 1)) } } -pub fn resolve_pattern_subject( - scope: Rc, - scrutinee_subject: Rc, -) -> Rc { - match (*scrutinee_subject).clone() { - PatternSubject::PatternResolved { - node: scrutinee_type, - .. - } => pattern_subject_from_node(resolve_scrutinee_type_node( - scope.type_env.clone(), - scrutinee_type.clone(), - )), - PatternSubject::PatternDynamic { - span: dynamic_span, .. - } => Rc::new(PatternSubject::PatternDynamic { - span: dynamic_span.clone(), - }), - PatternSubject::PatternLookupBlocked => Rc::new(PatternSubject::PatternLookupBlocked), +pub fn direct_call_product_field_names_match( + formal: Rc, + actual: Rc, + source_indices: Rc>>, +) -> bool { + { + let mut __all = true; + for pair in Rc::new( + formal + .children + .clone() + .iter() + .cloned() + .enumerate() + .map(|(i, v)| (i as i64, v)) + .collect::>(), + ) + .iter() + .cloned() + { + if !(match actual + .children + .clone() + .get(pair.0.clone() as usize) + .cloned() + { + Some(actual_field) => { + (field_node_name_at(pair.1.clone(), source_indices.clone()).as_str() + == field_node_name_at(actual_field.clone(), source_indices.clone()) + .as_str()) + } + None => false, + }) { + __all = false; + break; + } + } + __all } } -pub fn annotate_pattern_parent_enums( - pattern: Rc, - scrutinee_subject: Rc, - scope: Rc, -) -> Rc { - stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { - match (*pattern.clone()).clone() { - MatchPattern::VariantPattern { - name: variant_name, - field_bindings: bindings, - .. - } => { - let resolved_scrut = resolve_pattern_subject(scope.clone(), scrutinee_subject); - let inferred_parent = match (*resolved_scrut.clone()).clone() { - PatternSubject::PatternResolved { - node: resolved_scrut_node, - .. - } => { - let scrutinee_name = authored_name_at( - scope.type_env.clone().source_indices.clone(), - resolved_scrut_node.clone(), +pub fn direct_call_structural_pd3_mismatch( + formal: Rc, + actual: Rc, + env: Rc, + source_indices: Rc>>, +) -> bool { + { + let same_structural_carrier = + (structural_carrier_template_name(formal.clone(), source_indices.clone()).as_str() + == structural_carrier_template_name(actual.clone(), source_indices.clone()) + .as_str()); + let both_declared_identity = (((formal.binding_id.clone() != None) + && (actual.binding_id.clone() != None)) + && same_structural_carrier.clone()); + let both_element_carriers = + ((direct_call_element_collection_carrier(formal.clone(), source_indices.clone()) + && direct_call_element_collection_carrier(actual.clone(), source_indices.clone())) + && same_structural_carrier.clone()); + let formal_name = authored_name_at(source_indices.clone(), formal.clone()); + let actual_name = authored_name_at(source_indices.clone(), actual.clone()); + let formal_child_count = (formal.children.clone().len() as i64); + let actual_child_count = (actual.children.clone().len() as i64); + let record_twin_carriers = ((((((((formal.connective.clone() == Connective::Conj) + && (actual.connective.clone() == Connective::Conj)) + && (formal_name.clone().as_str() != "".to_string().as_str())) + && (actual_name.clone().as_str() != "".to_string().as_str())) + && (formal_name.clone().as_str() != actual_name.clone().as_str())) + && (formal_child_count.clone() > 0)) + && (formal_child_count.clone() == actual_child_count)) + && direct_call_product_field_names_match( + formal.clone(), + actual.clone(), + source_indices.clone(), + )); + ((((both_declared_identity || both_element_carriers) || record_twin_carriers) + && !direct_call_transparent_alias_pair( + env, + formal.clone(), + actual.clone(), + source_indices.clone(), + )) + && !node_type_compatible(formal.clone(), actual.clone(), source_indices.clone())) + } +} + +pub fn direct_call_arg_type_mismatch( + formal: Rc, + actual: Rc, + type_env: Rc, + module_name: String, + source_indices: Rc>>, +) -> bool { + if direct_call_transparent_alias_pair( + type_env.clone(), + formal.clone(), + actual.clone(), + source_indices.clone(), + ) { + false + } else { + if (type_node_is_callable(formal.clone()) || type_node_is_callable(actual.clone())) { + false + } else { + (((direct_call_structural_pd3_mismatch( + formal.clone(), + actual.clone(), + type_env.clone(), + source_indices.clone(), + ) || direct_call_plain_kernel_leaf_mismatch( + formal.clone(), + actual.clone(), + source_indices.clone(), + )) || nominal_call_arg_brand_mismatch( + formal.clone(), + actual.clone(), + source_indices.clone(), + )) || container_element_nominal_brand_mismatch( + formal.clone(), + actual.clone(), + type_env.clone(), + module_name, + source_indices.clone(), + )) + } + } +} + +pub fn direct_call_arg_mismatch_diags( + value_params: Rc>>, + typed_args: Rc>>, + call_subst: Rc>>, + generic_names: Rc>, + type_env: Rc, + module_name: String, +) -> Rc>> { + { + let source_indices = type_env.source_indices.clone(); + Rc::new({ + let mut __result = Vec::new(); + for pair in Rc::new( + value_params + .iter() + .cloned() + .enumerate() + .map(|(i, v)| (i as i64, v)) + .collect::>(), + ) + .iter() + .cloned() + { + __result.extend( + (*{ + let formal_raw = param_node_type_expr(pair.1.clone()); + let formal_subst = substitute_generics( + formal_raw.clone(), + call_subst.clone(), + source_indices.clone(), ); - let optional_cardinality_subject = - ((resolved_scrut_node.return_cardinality.clone() - == Cardinality::CardOptional) - && (scrutinee_name.clone().as_str() - != "Optional".to_string().as_str())); - let witness_container_subject = - (is_witness_type_name(scrutinee_name.clone()) - && ((variant_name.clone().as_str() - == "Holds".to_string().as_str()) - || (variant_name.clone().as_str() - == "Violates".to_string().as_str()))); - if (optional_cardinality_subject - && ((variant_name.clone().as_str() == "Present".to_string().as_str()) - || (variant_name.clone().as_str() - == "Absent".to_string().as_str()))) - { - Some("Optional".to_string()) - } else { - if witness_container_subject { - Some("Witness".to_string()) - } else { - { - let is_coproduct = (resolved_scrut_node.connective.clone() - == Connective::Disj); - if is_coproduct { - Some(scrutinee_name.clone()) + let formal_peeled_result = peel_nominal_alias_identity_result( + formal_subst.clone(), + type_env.clone(), + module_name.clone(), + ); + let formal_peeled = formal_peeled_result.node.clone(); + let formal_identity = + direct_call_arg_decl_identity(formal_peeled.clone(), type_env.clone()); + let formal = stamp_hidden_dependency_refs( + formal_peeled.clone(), + type_env.clone(), + source_indices.clone(), + ); + match typed_args.clone().get(pair.0.clone() as usize).cloned() { + Some(ta) => { + let actual_expr = arg_value(ta.clone()); + let actual_raw = resolved_type(actual_expr.clone()); + let actual_peeled_result = peel_nominal_alias_identity_result( + actual_raw.clone(), + type_env.clone(), + module_name.clone(), + ); + let actual_peeled = actual_peeled_result.node.clone(); + let actual_identity = direct_call_arg_decl_identity( + actual_peeled.clone(), + type_env.clone(), + ); + let actual = stamp_hidden_dependency_refs( + actual_peeled.clone(), + type_env.clone(), + source_indices.clone(), + ); + let peel_diags = v2_rt::concat( + formal_peeled_result.diagnostics.clone(), + actual_peeled_result.diagnostics.clone(), + ); + let arg_span = arg_value(ta.clone()).span.clone(); + if ((peel_diags.clone().len() as i64) > 0) { + peel_diags.clone() + } else { + if ((((direct_call_arg_is_typed_deferral( + formal_raw.clone(), + actual_expr.clone(), + actual_raw.clone(), + source_indices.clone(), + ) || node_contains_type_variable( + formal_subst.clone(), + )) || node_contains_type_variable(actual_raw.clone())) + || node_contains_generic_name( + formal_subst.clone(), + generic_names.clone(), + source_indices.clone(), + )) + || node_contains_generic_name( + actual_raw.clone(), + generic_names.clone(), + source_indices.clone(), + )) + { + Rc::new(vec![]) } else { - None + if (direct_call_transparent_alias_pair( + type_env.clone(), + formal_identity.clone(), + actual_identity.clone(), + source_indices.clone(), + ) || direct_call_transparent_alias_pair( + type_env.clone(), + formal.clone(), + actual.clone(), + source_indices.clone(), + )) { + Rc::new(vec![]) + } else { + if (direct_call_decl_identity_mismatch( + formal_identity.clone(), + actual_identity.clone(), + formal.clone(), + actual.clone(), + type_env.clone(), + source_indices.clone(), + ) || direct_call_arg_type_mismatch( + formal.clone(), + actual.clone(), + type_env.clone(), + module_name.clone(), + source_indices.clone(), + )) { + Rc::new(vec![type_mismatch_error( + node_type_shape( + formal.clone(), + source_indices.clone(), + ), + node_type_shape( + actual.clone(), + source_indices.clone(), + ), + arg_span.clone(), + module_name.clone(), + )]) + } else { + Rc::new(vec![]) + } + } } } } + None => formal_peeled_result.diagnostics.clone(), } - } - PatternSubject::PatternDynamic { span: _, .. } => None, - PatternSubject::PatternLookupBlocked => None, - }; - let annotated_variant_name = variant_name.clone(); - let variant_lookup = lookup_variant_in_type( - resolved_scrut.clone(), - variant_name.clone(), - scope.module_name.clone(), - scope.type_env.clone().source_indices.clone(), - (bindings.clone().len() as i64), + }) + .iter() + .cloned(), ); - let variant_subject = lookup_result_subject(variant_lookup); - let annotated_bindings = Rc::new({ - let mut __result = Vec::new(); - for binding in bindings.clone().iter().cloned() { - __result.push({ - let field_lookup = lookup_field_in_variant( - variant_subject.clone(), - field_binding_name_at( - binding.clone(), - scope.type_env.clone().source_indices.clone(), - ), - scope.module_name.clone(), - scope.type_env.clone().source_indices.clone(), - ); - let field_subject = lookup_result_subject(field_lookup.clone()); - make_field_binding_node( - field_binding_name_at( - binding.clone(), - scope.type_env.clone().source_indices.clone(), - ), - annotate_pattern_parent_enums( - field_binding_pattern(binding.clone()), - field_subject.clone(), - scope.clone(), - ), - binding.span.clone(), - node_name_span(binding.clone()), - ) - }); - } - __result - }); - match inferred_parent { - Some(parent_name) => Rc::new(MatchPattern::VariantPattern { - name: annotated_variant_name, - parent_enum: Some(parent_name.clone()), - field_bindings: annotated_bindings, - }), - None => Rc::new(MatchPattern::VariantPattern { - name: variant_name.clone(), - parent_enum: None, - field_bindings: annotated_bindings, - }), - } } - _ => pattern.clone(), - } - }) + __result + }) + } } -pub fn build_params_scope(scope: Rc, params: Rc>>) -> Rc { +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct Tier2bBt { + pub bt: Rc, + pub kernel_diags: Rc>>, +} + +pub fn infer_tier2b_builtin_with_kernel_diags( + func_name: String, + typed_args: Rc>>, + scope: Rc, + span: Rc, +) -> Rc { + if ((func_name.clone().as_str() == "lookup".to_string().as_str()) + || (func_name.clone().as_str() == "map_get".to_string().as_str())) { - let new_locals = params.iter().cloned().fold( - scope.locals.clone(), - |acc: Rc>>, p: Rc| { - v2_rt::rc_map_insert( - acc, - param_node_name_at(p.clone(), scope.type_env.clone().source_indices.clone()), - Rc::new(TypeBinding { - name: param_node_name_at( - p.clone(), - scope.type_env.clone().source_indices.clone(), - ), - resolved: param_node_type_expr(p.clone()), - provenance: Rc::new(SubValueRelation::PreservedValue), - }), - ) - }, - ); - Rc::new(InferScope { - type_env: scope.type_env.clone(), - func_env: scope.func_env.clone(), - locals: new_locals, - match_bound_names: scope.match_bound_names.clone(), - module_name: scope.module_name.clone(), - service_registry: scope.service_registry.clone(), - item_registry: scope.item_registry.clone(), - lambda_param_provenance: v2_rt::rc_empty_map::>(), - }) - } -} - -pub fn extend_scope( - scope: Rc, - name: String, - resolved: Rc, - provenance: Rc, -) -> Rc { - Rc::new(InferScope { - type_env: scope.type_env.clone(), - func_env: scope.func_env.clone(), - locals: v2_rt::rc_map_insert( - scope.locals.clone(), - name.clone(), - Rc::new(TypeBinding { - name: name.clone(), - resolved: resolved, - provenance: provenance, - }), - ), - match_bound_names: scope.match_bound_names.clone(), - module_name: scope.module_name.clone(), - service_registry: scope.service_registry.clone(), - item_registry: scope.item_registry.clone(), - lambda_param_provenance: scope.lambda_param_provenance.clone(), - }) -} - -pub fn extend_scope_match_bound( - scope: Rc, - name: String, - resolved: Rc, - provenance: Rc, -) -> Rc { - Rc::new(InferScope { - type_env: scope.type_env.clone(), - func_env: scope.func_env.clone(), - locals: v2_rt::rc_map_insert( - scope.locals.clone(), - name.clone(), - Rc::new(TypeBinding { - name: name.clone(), - resolved: resolved, - provenance: provenance, - }), - ), - match_bound_names: v2_rt::rc_map_insert( - scope.match_bound_names.clone(), - name.clone(), - true, - ), - module_name: scope.module_name.clone(), - service_registry: scope.service_registry.clone(), - item_registry: scope.item_registry.clone(), - lambda_param_provenance: scope.lambda_param_provenance.clone(), - }) -} - -pub fn extend_scope_with_params(scope: Rc, params: Rc>) -> Rc { - { - let new_locals = params.iter().cloned().fold( - scope.locals.clone(), - |acc: Rc>>, p: String| { - v2_rt::rc_map_insert( - acc, - p.clone(), - Rc::new(TypeBinding { - name: p.clone(), - resolved: type_variable_node("lambda_param".to_string()), - provenance: Rc::new(SubValueRelation::SubValueUnknown), - }), - ) + Rc::new(Tier2bBt { + bt: match typed_args.clone().first().cloned() { + Some(receiver_arg) => match arg_value(receiver_arg.clone()) + .inferred + .clone() + .as_deref() + .cloned() + { + Some(InferredNode::Resolved { + node: receiver_type, + .. + }) => { + match map_value_type_in_env(receiver_type.clone(), scope.type_env.clone()) { + Some(value_type) => { + if (func_name.clone().as_str() == "lookup".to_string().as_str()) { + witness_of_element(value_type.clone()) + } else { + with_optional_cardinality(value_type.clone()) + } + } + None => resolve_builtin_call_type(func_name.clone()), + } + } + _ => resolve_builtin_call_type(func_name.clone()), + }, + None => resolve_builtin_call_type(func_name.clone()), }, - ); - Rc::new(InferScope { - type_env: scope.type_env.clone(), - func_env: scope.func_env.clone(), - locals: new_locals, - match_bound_names: scope.match_bound_names.clone(), - module_name: scope.module_name.clone(), - service_registry: scope.service_registry.clone(), - item_registry: scope.item_registry.clone(), - lambda_param_provenance: scope.lambda_param_provenance.clone(), + kernel_diags: Rc::new(vec![]), }) - } -} - -pub fn scope_after_stmt_node( - stmt: Rc, - stmt_type: Rc, - scope: Rc, -) -> Rc { - match (*stmt.expr_data.clone()).clone() { - ExprData::ExprLet => { - if ((stmt.children.clone().len() as i64) <= 1) { - { - let val = match stmt.children.clone().first().cloned() { - Some(v) => v.clone(), - None => stmt.clone(), - }; - extend_scope( - scope.clone(), - let_binding_name_at( - stmt.clone(), - scope.type_env.clone().source_indices.clone(), - ), - stmt_type, - classify_binding_provenance(val, scope.clone()), - ) - } - } else { - scope.clone() - } - } - _ => scope.clone(), - } -} - -pub fn derive_field_provenance( - scope: Rc, - scrutinee_provenance: Rc, - scrutinee_subject: Rc, - variant_name: String, - field_name: String, -) -> Rc { - match (*scrutinee_provenance.clone()).clone() { - SubValueRelation::SubValueUnknown => Rc::new(SubValueRelation::SubValueUnknown), - _ => { - let scrut_type_name = match (*scrutinee_subject).clone() { - PatternSubject::PatternResolved { node: n, .. } => authored_name_at( - scope.type_env.clone().source_indices.clone(), - resolved_type(n.clone()), - ), - _ => "".to_string(), - }; - if (scrut_type_name.clone().as_str() == "".to_string().as_str()) { - Rc::new(SubValueRelation::SubValueUnknown) - } else { + } else { + if (func_name.clone().as_str() == "map_keys".to_string().as_str()) { + match typed_args.clone().first().cloned() { + Some(receiver_arg) => match arg_value(receiver_arg.clone()) + .inferred + .clone() + .as_deref() + .cloned() { - let ind_fields = - inductive_fields_for(scope.type_env.clone(), scrut_type_name.clone()); - let matching = Rc::new({ - let mut __result = Vec::new(); - for f in ind_fields.iter().cloned() { - if ((f.variant_name.clone().as_str() == variant_name.clone().as_str()) - && (f.field_name.clone().as_str() == field_name.clone().as_str())) - { - __result.push(f); + Some(InferredNode::Resolved { + node: receiver_type, + .. + }) => { + match map_key_type_in_env(receiver_type.clone(), scope.type_env.clone()) { + Some(key_type) => { + let lk = list_kernel_ty_from_element(key_type.clone()); + Rc::new(Tier2bBt { + bt: lk.ty.clone(), + kernel_diags: lk.miss_diags.clone(), + }) } + None => Rc::new(Tier2bBt { + bt: resolve_builtin_call_type(func_name.clone()), + kernel_diags: Rc::new(vec![]), + }), } - __result - }) - .first() - .cloned(); - match matching { - Some(ind_field) => { - compose_sub_value(scrutinee_provenance.clone(), ind_field.clone()) - } - None => Rc::new(SubValueRelation::SubValueUnknown), } - } + _ => Rc::new(Tier2bBt { + bt: resolve_builtin_call_type(func_name.clone()), + kernel_diags: Rc::new(vec![]), + }), + }, + None => Rc::new(Tier2bBt { + bt: resolve_builtin_call_type(func_name.clone()), + kernel_diags: Rc::new(vec![]), + }), } - } - } -} - -pub fn extend_scope_with_pattern_node( - scope: Rc, - pattern: Rc, - scrutinee_subject: Rc, - scrutinee_provenance: Rc, -) -> Rc { - stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || match (*pattern).clone() { - MatchPattern::Bind { name: n, .. } => Rc::new(PatternScopeResult { - scope: extend_scope_match_bound( - scope.clone(), - n.clone(), - pattern_binding_type(scrutinee_subject.clone()), - scrutinee_provenance.clone(), - ), - diagnostics: Rc::new(vec![]), - }), - MatchPattern::Wildcard => Rc::new(PatternScopeResult { - scope: scope.clone(), - diagnostics: Rc::new(vec![]), - }), - MatchPattern::LitPattern { value: _, .. } => Rc::new(PatternScopeResult { - scope: scope.clone(), - diagnostics: Rc::new(vec![]), - }), - MatchPattern::VariantPattern { - name: vname, - field_bindings: bindings, - .. - } => { - let resolved_scrut = resolve_pattern_subject(scope.clone(), scrutinee_subject.clone()); - let variant_lookup = lookup_variant_in_type( - resolved_scrut, - vname.clone(), - scope.module_name.clone(), - scope.type_env.clone().source_indices.clone(), - (bindings.clone().len() as i64), - ); - let variant_subject = lookup_result_subject(variant_lookup.clone()); - let variant_diags = variant_lookup.diagnostics.clone(); - bindings.clone().iter().cloned().fold( - Rc::new(PatternScopeResult { - scope: scope.clone(), - diagnostics: variant_diags, - }), - |acc: Rc, fb: Rc| { - let field_name = field_binding_name_at( - fb.clone(), - scope.type_env.clone().source_indices.clone(), - ); - let field_lookup = lookup_field_in_variant( - variant_subject.clone(), - field_name.clone(), - scope.module_name.clone(), - scope.type_env.clone().source_indices.clone(), - ); - let field_subject = lookup_result_subject(field_lookup.clone()); - let field_type = pattern_binding_type(field_subject.clone()); - let field_provenance = derive_field_provenance( - scope.clone(), - scrutinee_provenance.clone(), - scrutinee_subject.clone(), - vname.clone(), - field_name.clone(), - ); - let fb_pattern = field_binding_pattern(fb.clone()); - match (*fb_pattern.clone()).clone() { - MatchPattern::Bind { name: n, .. } => Rc::new(PatternScopeResult { - scope: extend_scope_match_bound( - acc.scope.clone(), - n.clone(), - field_type.clone(), - field_provenance.clone(), - ), - diagnostics: v2_rt::concat( - acc.diagnostics.clone(), - field_lookup.diagnostics.clone(), - ), - }), - _ => { - let nested = extend_scope_with_pattern_node( - acc.scope.clone(), - fb_pattern.clone(), - field_subject.clone(), - field_provenance.clone(), - ); - Rc::new(PatternScopeResult { - scope: nested.scope.clone(), - diagnostics: v2_rt::concat( - acc.diagnostics.clone(), - v2_rt::concat( - field_lookup.diagnostics.clone(), - nested.diagnostics.clone(), - ), - ), - }) - } - } - }, - ) - } - }) -} - -pub fn method_name_is(opt: Option, expected: String) -> bool { - if (opt.clone() == None) { - false - } else { - (opt.clone().unwrap().as_str() == expected.as_str()) - } -} - -pub fn arg_has_name( - arg: Rc, - name: String, - source_indices: Rc>>, -) -> bool { - { - let n = arg_name_at(arg, source_indices); - if (n.clone() == None) { - false } else { - (n.clone().unwrap().as_str() == name.as_str()) - } - } -} - -pub fn extract_fold_init_info( - method_name: Option, - method_args: Rc>>, - min_args: i64, - scope: Rc, - expected: Option>, -) -> Option> { - { - let is_fold = method_name_is(method_name, "fold".to_string()); - if (is_fold && ((method_args.clone().len() as i64) >= min_args)) { - { - let init_arg = match Rc::new({ - let mut __result = Vec::new(); - for a in method_args.clone().iter().cloned() { - if arg_has_name( - a.clone(), - "init".to_string(), - scope.type_env.clone().source_indices.clone(), + if (func_name.clone().as_str() == "map_values".to_string().as_str()) { + match typed_args.clone().first().cloned() { + Some(receiver_arg) => match arg_value(receiver_arg.clone()) + .inferred + .clone() + .as_deref() + .cloned() + { + Some(InferredNode::Resolved { + node: receiver_type, + .. + }) => match map_value_type_in_env( + receiver_type.clone(), + scope.type_env.clone(), ) { - __result.push(a); - } - } - __result - }) - .first() - .cloned() - { - Some(a) => Some(a.clone()), - None => method_args.clone().first().cloned(), - }; - match init_arg { - Some(ia) => { - let init_result = - infer_expr(arg_value(ia.clone()), scope.clone(), expected); - Some(Rc::new(ArgInferResult { - typed_arg: make_arg_node( - arg_name_at( - ia.clone(), - scope.type_env.clone().source_indices.clone(), - ), - init_result.typed.clone(), - ia.span.clone(), - ia.span.clone(), - ), - diagnostics: init_result.diagnostics.clone(), - })) - } - None => None, + Some(value_type) => { + let lv = list_kernel_ty_from_element(value_type.clone()); + Rc::new(Tier2bBt { + bt: lv.ty.clone(), + kernel_diags: lv.miss_diags.clone(), + }) + } + None => Rc::new(Tier2bBt { + bt: resolve_builtin_call_type(func_name.clone()), + kernel_diags: Rc::new(vec![]), + }), + }, + _ => Rc::new(Tier2bBt { + bt: resolve_builtin_call_type(func_name.clone()), + kernel_diags: Rc::new(vec![]), + }), + }, + None => Rc::new(Tier2bBt { + bt: resolve_builtin_call_type(func_name.clone()), + kernel_diags: Rc::new(vec![]), + }), } - } - } else { - None - } - } -} - -pub fn derive_element_provenance( - coll_expr: Rc, - elem_type: Rc, - scope: Rc, -) -> Rc { - { - let coll_prov = classify_binding_provenance(coll_expr, scope.clone()); - match (*coll_prov).clone() { - SubValueRelation::SubValueUnknown => Rc::new(SubValueRelation::SubValueUnknown), - _ => { - if (authored_name_at( - scope.type_env.clone().source_indices.clone(), - elem_type.clone(), - ) - .as_str() - == "".to_string().as_str()) + } else { + if (((func_name.clone().as_str() == "set_insert".to_string().as_str()) + || (func_name.clone().as_str() == "set_union".to_string().as_str())) + || (func_name.clone().as_str() == "set_contains".to_string().as_str())) { - Rc::new(SubValueRelation::SubValueUnknown) - } else { { - let ind_fields = inductive_fields_for( - scope.type_env.clone(), - authored_name_at( - scope.type_env.clone().source_indices.clone(), - elem_type.clone(), - ), - ); - let list_field = Rc::new({ - let mut __result = Vec::new(); - for f in ind_fields.iter().cloned() { - if match f.shape.clone() { - RecursionShape::ListRecursion => true, - _ => false, - } { - __result.push(f); - } - } - __result - }) - .first() - .cloned(); - match list_field { - Some(f) => { - Rc::new(SubValueRelation::IteratedSubValue { field: f.clone() }) + let operand_elem = if ((func_name.clone().as_str() + == "set_insert".to_string().as_str()) + || (func_name.clone().as_str() == "set_contains".to_string().as_str())) + { + match typed_args.clone().get(1 as usize).cloned() { + Some(insert_arg) => match arg_value(insert_arg.clone()) + .inferred + .clone() + .as_deref() + .cloned() + { + Some(InferredNode::Resolved { node: elem, .. }) => { + Some(elem.clone()) + } + _ => None, + }, + None => None, } - None => Rc::new(SubValueRelation::SubValueUnknown), - } + } else { + match typed_args.clone().get(1 as usize).cloned() { + Some(other_arg) => match arg_value(other_arg.clone()) + .inferred + .clone() + .as_deref() + .cloned() + { + Some(InferredNode::Resolved { + node: other_type, .. + }) => match set_element_type_in_env( + other_type.clone(), + scope.type_env.clone(), + ) { + Some(elem_slot) => Some(child_type_node(elem_slot.clone())), + None => None, + }, + _ => None, + }, + None => None, + } + }; + let recv_is_set = match typed_args.clone().first().cloned() { + Some(receiver_arg) => { + set_builtin_receiver_is_set(receiver_arg.clone(), scope.clone()) + } + None => false, + }; + let union_other_bad = + if (func_name.clone().as_str() == "set_union".to_string().as_str()) { + match typed_args.clone().get(1 as usize).cloned() { + Some(other_arg) => set_union_other_operand_is_resolved_non_set( + other_arg.clone(), + scope.clone(), + ), + None => false, + } + } else { + false + }; + let recv_elem = match typed_args.clone().first().cloned() { + Some(receiver_arg) => match arg_value(receiver_arg.clone()) + .inferred + .clone() + .as_deref() + .cloned() + { + Some(InferredNode::Resolved { + node: receiver_type, + .. + }) => set_element_type_from_receiver( + receiver_type.clone(), + scope.clone(), + ), + _ => None, + }, + None => None, + }; + let elem_mismatch = match recv_elem.clone() { + Some(re) => match operand_elem.clone() { + Some(oe) => set_element_types_mismatch( + re.clone(), + oe.clone(), + scope.type_env.clone().source_indices.clone(), + ), + None => false, + }, + None => false, + }; + let wrong_receiver_diags = if recv_is_set.clone() { + Rc::new(vec![]) + } else { + Rc::new(vec![inference_error( + v2_rt::concat( + func_name.clone(), + " receiver must be a Set".to_string(), + ), + span.clone(), + scope.module_name.clone(), + )]) + }; + let wrong_union_other_diags = if union_other_bad.clone() { + Rc::new(vec![inference_error( + "set_union second operand must be a Set".to_string(), + span.clone(), + scope.module_name.clone(), + )]) + } else { + Rc::new(vec![]) + }; + let mismatch_diags = if elem_mismatch.clone() { + Rc::new(vec![inference_error( + v2_rt::concat( + func_name.clone(), + " incompatible set element types".to_string(), + ), + span.clone(), + scope.module_name.clone(), + )]) + } else { + Rc::new(vec![]) + }; + let result_bt = if (func_name.clone().as_str() + == "set_contains".to_string().as_str()) + { + if (recv_is_set.clone() && !elem_mismatch.clone()) { + bool_type() + } else { + resolve_builtin_call_type(func_name.clone()) + } + } else { + match typed_args.clone().first().cloned() { + Some(receiver_arg) => { + if ((recv_is_set.clone() && !elem_mismatch.clone()) + && !union_other_bad.clone()) + { + match arg_value(receiver_arg.clone()) + .inferred + .clone() + .as_deref() + .cloned() + { + Some(InferredNode::Resolved { + node: receiver_type, + .. + }) => match recv_elem.clone() { + Some(_) => receiver_type.clone(), + None => match operand_elem.clone() { + Some(element) => { + set_kernel_ty_from_element(element.clone()) + .ty + .clone() + } + None => { + resolve_builtin_call_type(func_name.clone()) + } + }, + }, + _ => resolve_builtin_call_type(func_name.clone()), + } + } else { + resolve_builtin_call_type(func_name.clone()) + } + } + None => resolve_builtin_call_type(func_name.clone()), + } + }; + let build_diags = if (func_name.clone().as_str() + == "set_contains".to_string().as_str()) + { + Rc::new(vec![]) + } else { + match operand_elem.clone() { + Some(element) => { + if ((recv_is_set.clone() && !elem_mismatch.clone()) + && !union_other_bad.clone()) + { + set_kernel_ty_from_element(element.clone()) + .miss_diags + .clone() + } else { + Rc::new(vec![]) + } + } + None => Rc::new(vec![]), + } + }; + Rc::new(Tier2bBt { + bt: result_bt, + kernel_diags: v2_rt::concat( + wrong_receiver_diags, + v2_rt::concat( + wrong_union_other_diags, + v2_rt::concat(mismatch_diags, build_diags), + ), + ), + }) } + } else { + Rc::new(Tier2bBt { + bt: resolve_builtin_call_type(func_name.clone()), + kernel_diags: Rc::new(vec![]), + }) } } } } } -pub fn infer_method_args_with_fold( - method_name: Option, - method_args: Rc>>, - fold_info: Option>, - fold_acc_type: Rc, - element_type: Rc, - elem_provenance: Rc, +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct MethodPipeFallback { + pub result_ty: Rc, + pub kernel_diags: Rc>>, +} + +pub fn method_pipe_map_keys_values_fallback( + recv_rt: Rc, + method_name: String, scope: Rc, -) -> Rc>> { - { - let is_fold = method_name_is(method_name, "fold".to_string()); - Rc::new({ - let mut __result = Vec::new(); - for idx_pair in Rc::new( - method_args - .iter() - .cloned() - .enumerate() - .map(|(i, v)| (i as i64, v)) - .collect::>(), - ) - .iter() - .cloned() - { - __result.push({ - let a = idx_pair.1.clone(); - let idx = idx_pair.0.clone(); - let is_init_arg = (arg_has_name( - a.clone(), - "init".to_string(), - scope.type_env.clone().source_indices.clone(), - ) || ((arg_name_at( - a.clone(), - scope.type_env.clone().source_indices.clone(), - ) == None) - && (idx.clone() == 0))); - if ((is_fold.clone() && (fold_info.clone() != None)) && is_init_arg.clone()) { - match fold_info.clone() { - Some(fi) => fi.clone(), - None => infer_arg_with_element_type( - a.clone(), - element_type.clone(), - scope.clone(), - ), - } - } else { - if (is_fold.clone() && (fold_info.clone() != None)) { - { - let fold_params = Rc::new(vec![ - make_param_node( - "acc".to_string(), - fold_acc_type.clone(), - None, - no_span(), - no_span(), - ), - make_param_node( - "elem".to_string(), - element_type.clone(), - None, - no_span(), - no_span(), - ), - ]); - let fold_callable = Rc::new(Node { - name: "".to_string(), - span: no_span(), - ident_span: None, - children: Rc::new(vec![]), - connective: Connective::NoConnective, - params: fold_params.clone(), - inferred: None, - return_cardinality: Cardinality::Required, - uses: Rc::new(vec![]), - body: None, - transport: None, - properties: Rc::new(vec![]), - type_annotation: None, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }); - let lam_value = arg_value(a.clone()); - let prov_map = match (*elem_provenance.clone()).clone() { - SubValueRelation::SubValueUnknown => { - v2_rt::rc_empty_map::>() - } - _ => v2_rt::rc_map_insert( - v2_rt::rc_empty_map::>(), - "elem".to_string(), - elem_provenance.clone(), - ), - }; - let fold_scope = Rc::new(InferScope { - type_env: scope.type_env.clone(), - func_env: scope.func_env.clone(), - locals: scope.locals.clone(), - match_bound_names: scope.match_bound_names.clone(), - module_name: scope.module_name.clone(), - service_registry: scope.service_registry.clone(), - item_registry: scope.item_registry.clone(), - lambda_param_provenance: prov_map.clone(), - }); - let ar = infer_expr( - lam_value.clone(), - fold_scope.clone(), - Some(fold_callable.clone()), - ); - Rc::new(ArgInferResult { - typed_arg: make_arg_node( - arg_name_at( - a.clone(), - scope.type_env.clone().source_indices.clone(), - ), - ar.typed.clone(), - a.span.clone(), - a.span.clone(), - ), - diagnostics: ar.diagnostics.clone(), - }) - } + span: Rc, +) -> Rc { + if (method_name.clone().as_str() == "map_keys".to_string().as_str()) { + match map_key_type_in_env(recv_rt.clone(), scope.type_env.clone()) { + Some(key_type) => { + let lk = list_kernel_ty_from_element(key_type.clone()); + Rc::new(MethodPipeFallback { + result_ty: lk.ty.clone(), + kernel_diags: lk.miss_diags.clone(), + }) + } + None => Rc::new(MethodPipeFallback { + result_ty: recv_rt.clone(), + kernel_diags: Rc::new(vec![]), + }), + } + } else { + if (method_name.clone().as_str() == "map_values".to_string().as_str()) { + match map_value_type_in_env(recv_rt.clone(), scope.type_env.clone()) { + Some(value_type) => { + let lv = list_kernel_ty_from_element(value_type.clone()); + Rc::new(MethodPipeFallback { + result_ty: lv.ty.clone(), + kernel_diags: lv.miss_diags.clone(), + }) + } + None => Rc::new(MethodPipeFallback { + result_ty: recv_rt.clone(), + kernel_diags: Rc::new(vec![]), + }), + } + } else { + Rc::new(MethodPipeFallback { + result_ty: recv_rt.clone(), + kernel_diags: Rc::new(vec![]), + }) + } + } +} + +pub fn categorized_error( + message: String, + span: Rc, + module_name: String, + category: String, +) -> Rc { + make_error_node( + Rc::new(CompilerDiagnostic::InternalError { + message: message, + span: span, + }), + module_name, + ) +} + +pub fn validate_cast( + source_inferred: Option>, + target_name: String, + span: Rc, + source_indices: Rc>>, + module_name: String, +) -> Option> { + match source_inferred.as_deref().cloned() { + Some(InferredNode::Resolved { node: src_node, .. }) => { + let source_name = authored_name_at(source_indices, src_node.clone()); + if (source_name.clone().as_str() == target_name.clone().as_str()) { + None + } else { + if !is_dag_cast_domain_type(source_name.clone()) { + None + } else { + if !is_dag_cast_domain_type(target_name.clone()) { + None + } else { + if dag_can_cast(source_name.clone(), target_name.clone()) { + None } else { { - let nf_lam_value = arg_value(a.clone()); - let nf_prov_map = match (*elem_provenance.clone()).clone() { - SubValueRelation::SubValueUnknown => { - v2_rt::rc_empty_map::>() - } - _ => v2_rt::rc_map_insert( - v2_rt::rc_empty_map::>(), - "elem".to_string(), - elem_provenance.clone(), + let msg = v2_rt::concat( + v2_rt::concat( + v2_rt::concat( + "invalid cast: ".to_string(), + source_name.clone(), + ), + " as ".to_string(), ), - }; - let nf_scope = if is_lambda_expr(nf_lam_value.clone()) { - Rc::new(InferScope { - type_env: scope.type_env.clone(), - func_env: scope.func_env.clone(), - locals: scope.locals.clone(), - match_bound_names: scope.match_bound_names.clone(), - module_name: scope.module_name.clone(), - service_registry: scope.service_registry.clone(), - item_registry: scope.item_registry.clone(), - lambda_param_provenance: nf_prov_map.clone(), - }) - } else { - scope.clone() - }; - infer_arg_with_element_type( - a.clone(), - element_type.clone(), - nf_scope.clone(), - ) + target_name.clone(), + ); + let diag = Rc::new(CompilerDiagnostic::InternalError { + message: msg, + span: span, + }); + Some(make_error_node(diag, module_name)) } } } - }); + } } - __result - }) + } + _ => None, } } -pub fn is_lambda_expr(e: Rc) -> bool { - match (*e.expr_data.clone()).clone() { - ExprData::ExprLambda => true, - _ => false, - } +pub fn type_variable_node(id: String) -> Rc { + Rc::new(Node { + name: "".to_string(), + span: make_span(0, 0), + ident_span: None, + children: Rc::new(vec![]), + connective: Connective::NoConnective, + params: Rc::new(vec![]), + inferred: Some(Rc::new(InferredNode::TypeVariable { id: id })), + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + transport: None, + properties: Rc::new(vec![]), + type_annotation: None, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }) } -pub fn seed_override_map() -> Rc>> { - Rc::new(vec!["".to_string()]).iter().cloned().fold( - v2_rt::rc_empty_map::>(), - |acc: Rc>>, k: String| { - v2_rt::rc_map_insert(acc, k.clone(), unit_type()) - }, - ) +pub fn is_type_variable(inferred: Rc) -> bool { + match (*inferred).clone() { + InferredNode::TypeVariable { id: _, .. } => true, + _ => false, + } } -pub fn fold_override_map(key: String, value: Rc) -> Rc>> { - v2_rt::rc_map_insert(seed_override_map(), key, value) +pub fn inferred_or_error( + result: Option>, + fallback_message: String, + fallback_span: Rc, +) -> Rc { + match result { + Some(inferred) => inferred.clone(), + None => Rc::new(InferredNode::CompilerError { + message: fallback_message, + span: fallback_span, + }), + } } -pub fn empty_override_map() -> Rc>> { - seed_override_map() +pub fn resolve_pattern_subject( + scope: Rc, + scrutinee_subject: Rc, +) -> Rc { + match (*scrutinee_subject).clone() { + PatternSubject::PatternResolved { + node: scrutinee_type, + .. + } => pattern_subject_from_node(resolve_scrutinee_type_node( + scope.type_env.clone(), + scrutinee_type.clone(), + )), + PatternSubject::PatternDynamic { + span: dynamic_span, .. + } => Rc::new(PatternSubject::PatternDynamic { + span: dynamic_span.clone(), + }), + PatternSubject::PatternLookupBlocked => Rc::new(PatternSubject::PatternLookupBlocked), + } } -pub fn infer_arg_with_element_type( - arg: Rc, - element_type: Rc, - scope: Rc, -) -> Rc { - { - let ar = infer_expr(arg_value(arg.clone()), scope.clone(), Some(element_type)); - Rc::new(ArgInferResult { - typed_arg: make_arg_node( - arg_name_at(arg.clone(), scope.type_env.clone().source_indices.clone()), - ar.typed.clone(), - arg.span.clone(), - arg.span.clone(), - ), - diagnostics: ar.diagnostics.clone(), - }) - } -} - -pub fn infer_expr( - texpr: Rc, +pub fn annotate_pattern_parent_enums( + pattern: Rc, + scrutinee_subject: Rc, scope: Rc, - expected: Option>, -) -> Rc { +) -> Rc { stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { - match (*texpr.expr_data.clone()).clone() { - ExprData::ExprLiteral { value: lit, .. } => { - let span = texpr.span.clone(); - ok_infer(make_expr_node( - Rc::new(ExprData::ExprLiteral { value: lit.clone() }), - Rc::new(vec![]), - Some(Rc::new(InferredNode::Resolved { - node: infer_literal_node(lit.clone()), - })), - span.clone(), - )) - } - ExprData::ExprError { kind, message, .. } => { - let span = texpr.span.clone(); - Rc::new(InferResult { - typed: make_expr_error_node(kind.clone(), message.clone(), span.clone()), - diagnostics: Rc::new(vec![]), - }) - } - ExprData::ExprVar { - binding_kind: _, .. + match (*pattern.clone()).clone() { + MatchPattern::VariantPattern { + name: variant_name, + field_bindings: bindings, + .. } => { - let name = - expr_var_name_at(texpr.clone(), scope.type_env.clone().source_indices.clone()); - let span = texpr.span.clone(); - match v2_rt::map_get(&scope.locals.clone(), name.clone()) { - Some(binding) => { - let binding_kind = infer_var_binding_kind(scope.clone(), name.clone()); - ok_infer(make_named_expr_node( - name.clone(), - Rc::new(ExprData::ExprVar { - binding_kind: Some(binding_kind), - }), - Rc::new(vec![]), - Some(Rc::new(InferredNode::Resolved { - node: binding.resolved.clone(), - })), - span.clone(), - span.clone(), - )) - } - None => match lookup_func_sig(scope.func_env.clone(), name.clone()) { - Some(fsig) => { - if ((fsig.params.clone().len() as i64) == 0) { - ok_infer(make_named_expr_node( - name.clone(), - Rc::new(ExprData::ExprCall { - call_semantics: Some(CallSemantics::PlainCallSemantics), - descent_evidence: None, - }), - Rc::new(vec![]), - Some(Rc::new(InferredNode::Resolved { - node: fsig.inferred.clone(), - })), - span.clone(), - span.clone(), - )) + let resolved_scrut = resolve_pattern_subject(scope.clone(), scrutinee_subject); + let inferred_parent = match (*resolved_scrut.clone()).clone() { + PatternSubject::PatternResolved { + node: resolved_scrut_node, + .. + } => { + let scrutinee_name = authored_name_at( + scope.type_env.clone().source_indices.clone(), + resolved_scrut_node.clone(), + ); + let optional_cardinality_subject = + ((resolved_scrut_node.return_cardinality.clone() + == Cardinality::CardOptional) + && (scrutinee_name.clone().as_str() + != "Optional".to_string().as_str())); + let witness_container_subject = + (is_witness_type_name(scrutinee_name.clone()) + && ((variant_name.clone().as_str() + == "Holds".to_string().as_str()) + || (variant_name.clone().as_str() + == "Violates".to_string().as_str()))); + if (optional_cardinality_subject + && ((variant_name.clone().as_str() == "Present".to_string().as_str()) + || (variant_name.clone().as_str() + == "Absent".to_string().as_str()))) + { + Some("Optional".to_string()) + } else { + if witness_container_subject { + Some("Witness".to_string()) } else { - ok_infer(make_named_expr_node( - name.clone(), - Rc::new(ExprData::ExprVar { - binding_kind: Some(Rc::new( - VarBindingKind::FunctionValueBinding, - )), - }), - Rc::new(vec![]), - Some(Rc::new(InferredNode::Resolved { - node: resolved_callable_type( - fsig.params.clone(), - fsig.inferred.clone(), - ), - })), - span.clone(), - span.clone(), - )) + { + let is_coproduct = (resolved_scrut_node.connective.clone() + == Connective::Disj); + if is_coproduct { + Some(scrutinee_name.clone()) + } else { + None + } + } } } - None => { - let err_texpr = make_named_expr_node( - name.clone(), - Rc::new(ExprData::ExprVar { binding_kind: None }), - Rc::new(vec![]), - Some(Rc::new(InferredNode::Resolved { node: error_type() })), - span.clone(), - span.clone(), - ); - Rc::new(InferResult { - typed: err_texpr, - diagnostics: Rc::new(vec![inference_error( - v2_rt::concat( - v2_rt::concat( - "undefined variable '".to_string(), - name.clone(), - ), - "'".to_string(), - ), - span.clone(), - scope.module_name.clone(), - )]), - }) - } - }, - } - } - ExprData::ExprFieldAccess { summary: _, .. } => { - let field_name = field_access_field_at( - texpr.clone(), + } + PatternSubject::PatternDynamic { span: _, .. } => None, + PatternSubject::PatternLookupBlocked => None, + }; + let annotated_variant_name = variant_name.clone(); + let variant_lookup = lookup_variant_in_type( + resolved_scrut.clone(), + variant_name.clone(), + scope.module_name.clone(), scope.type_env.clone().source_indices.clone(), + (bindings.clone().len() as i64), ); - let span = texpr.span.clone(); - let base_expr = field_access_base(texpr.clone()); - let base_result = infer_expr(base_expr, scope.clone(), None); - let base_typed = base_result.typed.clone(); - let base_diags = base_result.diagnostics.clone(); - let base_rt = resolved_type(base_typed.clone()); - let resolved_base = - resolve_scrutinee_type_node(scope.type_env.clone(), base_rt.clone()); - let resolved_base_is_error = if (resolved_base.inferred.clone() != None) { - is_compiler_error(resolved_base.inferred.clone().clone().unwrap()) - } else { - false - }; - if resolved_base_is_error { - Rc::new(InferResult { - typed: make_expr_error_node( - ExprErrorKind::SemanticExprError, - "error type cascade".to_string(), - span.clone(), - ), - diagnostics: base_diags, - }) - } else { - match lookup_field_type_node( - resolved_base.clone(), - field_name.clone(), - scope.type_env.clone().source_indices.clone(), - ) { - Some(field_type) => { - let field_summary = field_summary_for_type( - base_rt.clone(), - scope.type_env.clone(), - field_name.clone(), - ); - let fa_texpr = make_named_expr_node( - field_name.clone(), - Rc::new(ExprData::ExprFieldAccess { - summary: field_summary, - }), - Rc::new(vec![base_typed.clone()]), - Some(Rc::new(InferredNode::Resolved { - node: field_type.clone(), - })), - span.clone(), - node_name_span(texpr.clone()), + let variant_subject = lookup_result_subject(variant_lookup); + let annotated_bindings = Rc::new({ + let mut __result = Vec::new(); + for binding in bindings.clone().iter().cloned() { + __result.push({ + let field_lookup = lookup_field_in_variant( + variant_subject.clone(), + field_binding_name_at( + binding.clone(), + scope.type_env.clone().source_indices.clone(), + ), + scope.module_name.clone(), + scope.type_env.clone().source_indices.clone(), ); - Rc::new(InferResult { - typed: fa_texpr, - diagnostics: base_diags, - }) - } - None => { - let base_is_type_var = if (resolved_base.inferred.clone() != None) { - is_type_variable(resolved_base.inferred.clone().clone().unwrap()) - } else { - false - }; - if base_is_type_var { - { - let fa_texpr = make_named_expr_node( - field_name.clone(), - Rc::new(ExprData::ExprFieldAccess { - summary: Some(Rc::new(FieldSummary { - access_style: FieldAccessStyle::StoredField, - value_shape: FieldValueShape::PlainValue, - })), - }), - Rc::new(vec![base_typed.clone()]), - Some(Rc::new(InferredNode::TypeVariable { - id: "field_of_type_var".to_string(), - })), - span.clone(), - node_name_span(texpr.clone()), - ); - Rc::new(InferResult { - typed: fa_texpr, - diagnostics: base_diags, - }) - } - } else { - match check_service_field_access_node( - base_rt.clone(), - field_name.clone(), - scope.service_registry.clone(), + let field_subject = lookup_result_subject(field_lookup.clone()); + make_field_binding_node( + field_binding_name_at( + binding.clone(), scope.type_env.clone().source_indices.clone(), - ) { - Some(svc_type) => { - let fa_texpr = make_named_expr_node( - field_name.clone(), - Rc::new(ExprData::ExprFieldAccess { - summary: Some(Rc::new(FieldSummary { - access_style: FieldAccessStyle::StoredField, - value_shape: FieldValueShape::PlainValue, - })), - }), - Rc::new(vec![base_typed.clone()]), - Some(Rc::new(InferredNode::Resolved { - node: svc_type.clone(), - })), - span.clone(), - node_name_span(texpr.clone()), - ); - Rc::new(InferResult { - typed: fa_texpr, - diagnostics: base_diags, - }) - } - None => { - let error_message = v2_rt::concat( - v2_rt::concat( - v2_rt::concat( - v2_rt::concat( - "no field '".to_string(), - field_name.clone(), - ), - "' on type '".to_string(), - ), - authored_name_at( - scope.type_env.clone().source_indices.clone(), - resolved_base.clone(), - ), - ), - "'".to_string(), - ); - let fa_texpr = make_expr_error_node( - ExprErrorKind::SemanticExprError, - error_message.clone(), - span.clone(), - ); - Rc::new(InferResult { - typed: fa_texpr, - diagnostics: v2_rt::concat( - base_diags, - Rc::new(vec![inference_error( - error_message.clone(), - span.clone(), - scope.module_name.clone(), - )]), - ), - }) - } - } - } - } + ), + annotate_pattern_parent_enums( + field_binding_pattern(binding.clone()), + field_subject.clone(), + scope.clone(), + ), + binding.span.clone(), + node_name_span(binding.clone()), + ) + }); } + __result + }); + match inferred_parent { + Some(parent_name) => Rc::new(MatchPattern::VariantPattern { + name: annotated_variant_name, + parent_enum: Some(parent_name.clone()), + field_bindings: annotated_bindings, + }), + None => Rc::new(MatchPattern::VariantPattern { + name: variant_name.clone(), + parent_enum: None, + field_bindings: annotated_bindings, + }), } } - ExprData::ExprCall { .. } => { - let func_name = - expr_call_func_at(texpr.clone(), scope.type_env.clone().source_indices.clone()); - let span = texpr.span.clone(); - let call_args = texpr.children.clone(); - let sig = lookup_func_sig(scope.func_env.clone(), func_name.clone()); - let sig_params = match sig.clone() { - Some(s) => s.params.clone(), - None => Rc::new(vec![]), - }; - let has_lambda = { - let mut __found = false; - for a in call_args.clone().iter().cloned() { - if is_lambda_expr(arg_value(a.clone())) { - __found = true; - break; - } - } - __found - }; - let call_method_args = Rc::new( - call_args - .clone() - .iter() - .cloned() - .skip(1 as usize) - .collect::>(), - ); - let call_method_name = Some(func_name.clone()); - let call_fold_info = extract_fold_init_info( - call_method_name.clone(), - call_method_args.clone(), - 2, - scope.clone(), - expected.clone(), - ); - let call_fold_acc_type = match call_fold_info.clone() { - Some(fi) => resolved_type(arg_value(fi.typed_arg.clone())), - None => error_type(), - }; - let arg_call = if ((has_lambda && ((call_args.clone().len() as i64) >= 2)) - && (sig.clone() == None)) + _ => pattern.clone(), + } + }) +} + +pub fn build_params_scope(scope: Rc, params: Rc>>) -> Rc { + { + let new_locals = params.iter().cloned().fold( + scope.locals.clone(), + |acc: Rc>>, p: Rc| { + v2_rt::rc_map_insert( + acc, + param_node_name_at(p.clone(), scope.type_env.clone().source_indices.clone()), + Rc::new(TypeBinding { + name: param_node_name_at( + p.clone(), + scope.type_env.clone().source_indices.clone(), + ), + resolved: param_node_type_expr(p.clone()), + provenance: Rc::new(SubValueRelation::PreservedValue), + }), + ) + }, + ); + Rc::new(InferScope { + type_env: scope.type_env.clone(), + func_env: scope.func_env.clone(), + locals: new_locals, + variant_collisions: scope.variant_collisions.clone(), + match_bound_names: scope.match_bound_names.clone(), + module_name: scope.module_name.clone(), + service_registry: scope.service_registry.clone(), + item_registry: scope.item_registry.clone(), + lambda_param_provenance: v2_rt::rc_empty_map::>(), + }) + } +} + +pub fn extend_scope( + scope: Rc, + name: String, + resolved: Rc, + provenance: Rc, +) -> Rc { + Rc::new(InferScope { + type_env: scope.type_env.clone(), + func_env: scope.func_env.clone(), + locals: v2_rt::rc_map_insert( + scope.locals.clone(), + name.clone(), + Rc::new(TypeBinding { + name: name.clone(), + resolved: resolved, + provenance: provenance, + }), + ), + variant_collisions: scope.variant_collisions.clone(), + match_bound_names: scope.match_bound_names.clone(), + module_name: scope.module_name.clone(), + service_registry: scope.service_registry.clone(), + item_registry: scope.item_registry.clone(), + lambda_param_provenance: scope.lambda_param_provenance.clone(), + }) +} + +pub fn extend_scope_match_bound( + scope: Rc, + name: String, + resolved: Rc, + provenance: Rc, +) -> Rc { + Rc::new(InferScope { + type_env: scope.type_env.clone(), + func_env: scope.func_env.clone(), + locals: v2_rt::rc_map_insert( + scope.locals.clone(), + name.clone(), + Rc::new(TypeBinding { + name: name.clone(), + resolved: resolved, + provenance: provenance, + }), + ), + variant_collisions: scope.variant_collisions.clone(), + match_bound_names: v2_rt::rc_map_insert( + scope.match_bound_names.clone(), + name.clone(), + true, + ), + module_name: scope.module_name.clone(), + service_registry: scope.service_registry.clone(), + item_registry: scope.item_registry.clone(), + lambda_param_provenance: scope.lambda_param_provenance.clone(), + }) +} + +pub fn extend_scope_with_params(scope: Rc, params: Rc>) -> Rc { + { + let new_locals = params.iter().cloned().fold( + scope.locals.clone(), + |acc: Rc>>, p: String| { + v2_rt::rc_map_insert( + acc, + p.clone(), + Rc::new(TypeBinding { + name: p.clone(), + resolved: type_variable_node("lambda_param".to_string()), + provenance: Rc::new(SubValueRelation::SubValueUnknown), + }), + ) + }, + ); + Rc::new(InferScope { + type_env: scope.type_env.clone(), + func_env: scope.func_env.clone(), + locals: new_locals, + variant_collisions: scope.variant_collisions.clone(), + match_bound_names: scope.match_bound_names.clone(), + module_name: scope.module_name.clone(), + service_registry: scope.service_registry.clone(), + item_registry: scope.item_registry.clone(), + lambda_param_provenance: scope.lambda_param_provenance.clone(), + }) + } +} + +pub fn scope_after_stmt_node( + stmt: Rc, + stmt_type: Rc, + scope: Rc, +) -> Rc { + match (*stmt.expr_data.clone()).clone() { + ExprData::ExprLet => { + if ((stmt.children.clone().len() as i64) <= 1) { { - Rc::new(ArgGenericFoldState { - subst: v2_rt::rc_empty_map::>(), + let val = match stmt.children.clone().first().cloned() { + Some(v) => v.clone(), + None => stmt.clone(), + }; + extend_scope( + scope.clone(), + let_binding_name_at( + stmt.clone(), + scope.type_env.clone().source_indices.clone(), + ), + stmt_type, + classify_binding_provenance(val, scope.clone()), + ) + } + } else { + scope.clone() + } + } + _ => scope.clone(), + } +} + +pub fn derive_field_provenance( + scope: Rc, + scrutinee_provenance: Rc, + scrutinee_subject: Rc, + variant_name: String, + field_name: String, +) -> Rc { + match (*scrutinee_provenance.clone()).clone() { + SubValueRelation::SubValueUnknown => Rc::new(SubValueRelation::SubValueUnknown), + _ => { + let scrut_type_name = match (*scrutinee_subject).clone() { + PatternSubject::PatternResolved { node: n, .. } => authored_name_at( + scope.type_env.clone().source_indices.clone(), + resolved_type(n.clone()), + ), + _ => "".to_string(), + }; + if (scrut_type_name.clone().as_str() == "".to_string().as_str()) { + Rc::new(SubValueRelation::SubValueUnknown) + } else { + { + let ind_fields = + inductive_fields_for(scope.type_env.clone(), scrut_type_name.clone()); + let matching = Rc::new({ + let mut __result = Vec::new(); + for f in ind_fields.iter().cloned() { + if ((f.variant_name.clone().as_str() == variant_name.clone().as_str()) + && (f.field_name.clone().as_str() == field_name.clone().as_str())) + { + __result.push(f); + } + } + __result + }) + .first() + .cloned(); + match matching { + Some(ind_field) => { + compose_sub_value(scrutinee_provenance.clone(), ind_field.clone()) + } + None => Rc::new(SubValueRelation::SubValueUnknown), + } + } + } + } + } +} + +pub fn extend_scope_with_pattern_node( + scope: Rc, + pattern: Rc, + scrutinee_subject: Rc, + scrutinee_provenance: Rc, +) -> Rc { + stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || match (*pattern).clone() { + MatchPattern::Bind { name: n, .. } => Rc::new(PatternScopeResult { + scope: extend_scope_match_bound( + scope.clone(), + n.clone(), + pattern_binding_type(scrutinee_subject.clone()), + scrutinee_provenance.clone(), + ), + diagnostics: Rc::new(vec![]), + }), + MatchPattern::Wildcard => Rc::new(PatternScopeResult { + scope: scope.clone(), + diagnostics: Rc::new(vec![]), + }), + MatchPattern::LitPattern { value: _, .. } => Rc::new(PatternScopeResult { + scope: scope.clone(), + diagnostics: Rc::new(vec![]), + }), + MatchPattern::VariantPattern { + name: vname, + field_bindings: bindings, + .. + } => { + let resolved_scrut = resolve_pattern_subject(scope.clone(), scrutinee_subject.clone()); + let variant_lookup = lookup_variant_in_type( + resolved_scrut, + vname.clone(), + scope.module_name.clone(), + scope.type_env.clone().source_indices.clone(), + (bindings.clone().len() as i64), + ); + let variant_subject = lookup_result_subject(variant_lookup.clone()); + let variant_diags = variant_lookup.diagnostics.clone(); + bindings.clone().iter().cloned().fold( + Rc::new(PatternScopeResult { + scope: scope.clone(), + diagnostics: variant_diags, + }), + |acc: Rc, fb: Rc| { + let field_name = field_binding_name_at( + fb.clone(), + scope.type_env.clone().source_indices.clone(), + ); + let field_lookup = lookup_field_in_variant( + variant_subject.clone(), + field_name.clone(), + scope.module_name.clone(), + scope.type_env.clone().source_indices.clone(), + ); + let field_subject = lookup_result_subject(field_lookup.clone()); + let field_type = pattern_binding_type(field_subject.clone()); + let field_provenance = derive_field_provenance( + scope.clone(), + scrutinee_provenance.clone(), + scrutinee_subject.clone(), + vname.clone(), + field_name.clone(), + ); + let fb_pattern = field_binding_pattern(fb.clone()); + match (*fb_pattern.clone()).clone() { + MatchPattern::Bind { name: n, .. } => Rc::new(PatternScopeResult { + scope: extend_scope_match_bound( + acc.scope.clone(), + n.clone(), + field_type.clone(), + field_provenance.clone(), + ), + diagnostics: v2_rt::concat( + acc.diagnostics.clone(), + field_lookup.diagnostics.clone(), + ), + }), + _ => { + let nested = extend_scope_with_pattern_node( + acc.scope.clone(), + fb_pattern.clone(), + field_subject.clone(), + field_provenance.clone(), + ); + Rc::new(PatternScopeResult { + scope: nested.scope.clone(), + diagnostics: v2_rt::concat( + acc.diagnostics.clone(), + v2_rt::concat( + field_lookup.diagnostics.clone(), + nested.diagnostics.clone(), + ), + ), + }) + } + } + }, + ) + } + }) +} + +pub fn method_name_is(opt: Option, expected: String) -> bool { + match opt { + Some(name) => (name.clone().as_str() == expected.as_str()), + None => false, + } +} + +pub fn arg_has_name( + arg: Rc, + name: String, + source_indices: Rc>>, +) -> bool { + { + let n = arg_name_at(arg, source_indices); + match n { + Some(actual) => (actual.clone().as_str() == name.as_str()), + None => false, + } + } +} + +pub fn extract_fold_init_info( + method_name: Option, + method_args: Rc>>, + min_args: i64, + scope: Rc, + expected: Option>, +) -> Option> { + { + let is_fold = method_name_is(method_name, "fold".to_string()); + if (is_fold && ((method_args.clone().len() as i64) >= min_args)) { + { + let init_arg = match Rc::new({ + let mut __result = Vec::new(); + for a in method_args.clone().iter().cloned() { + if arg_has_name( + a.clone(), + "init".to_string(), + scope.type_env.clone().source_indices.clone(), + ) { + __result.push(a); + } + } + __result + }) + .first() + .cloned() + { + Some(a) => Some(a.clone()), + None => method_args.clone().first().cloned(), + }; + match init_arg { + Some(ia) => { + let init_result = + infer_expr(arg_value(ia.clone()), scope.clone(), expected); + Some(Rc::new(ArgInferResult { + typed_arg: make_arg_node( + arg_name_at( + ia.clone(), + scope.type_env.clone().source_indices.clone(), + ), + init_result.typed.clone(), + ia.span.clone(), + ia.span.clone(), + ), + diagnostics: init_result.diagnostics.clone(), + })) + } + None => None, + } + } + } else { + None + } + } +} + +pub fn derive_element_provenance( + coll_expr: Rc, + elem_type: Rc, + scope: Rc, +) -> Rc { + { + let coll_prov = classify_binding_provenance(coll_expr, scope.clone()); + match (*coll_prov).clone() { + SubValueRelation::SubValueUnknown => Rc::new(SubValueRelation::SubValueUnknown), + _ => { + if (authored_name_at( + scope.type_env.clone().source_indices.clone(), + elem_type.clone(), + ) + .as_str() + == "".to_string().as_str()) + { + Rc::new(SubValueRelation::SubValueUnknown) + } else { + { + let ind_fields = inductive_fields_for( + scope.type_env.clone(), + authored_name_at( + scope.type_env.clone().source_indices.clone(), + elem_type.clone(), + ), + ); + let list_field = Rc::new({ + let mut __result = Vec::new(); + for f in ind_fields.iter().cloned() { + if match f.shape.clone() { + RecursionShape::ListRecursion => true, + _ => false, + } { + __result.push(f); + } + } + __result + }) + .first() + .cloned(); + match list_field { + Some(f) => { + Rc::new(SubValueRelation::IteratedSubValue { field: f.clone() }) + } + None => Rc::new(SubValueRelation::SubValueUnknown), + } + } + } + } + } + } +} + +pub fn infer_method_args_with_fold( + method_name: Option, + method_args: Rc>>, + fold_info: Option>, + fold_acc_type: Rc, + element_type: Rc, + elem_provenance: Rc, + scope: Rc, +) -> Rc>> { + { + let is_fold = method_name_is(method_name, "fold".to_string()); + Rc::new({ + let mut __result = Vec::new(); + for idx_pair in Rc::new( + method_args + .iter() + .cloned() + .enumerate() + .map(|(i, v)| (i as i64, v)) + .collect::>(), + ) + .iter() + .cloned() + { + __result.push({ + let a = idx_pair.1.clone(); + let idx = idx_pair.0.clone(); + let is_init_arg = (arg_has_name( + a.clone(), + "init".to_string(), + scope.type_env.clone().source_indices.clone(), + ) || ((arg_name_at( + a.clone(), + scope.type_env.clone().source_indices.clone(), + ) == None) + && (idx.clone() == 0))); + if ((is_fold.clone() && (fold_info.clone() != None)) && is_init_arg.clone()) { + match fold_info.clone() { + Some(fi) => fi.clone(), + None => infer_arg_with_element_type( + a.clone(), + element_type.clone(), + scope.clone(), + ), + } + } else { + if (is_fold.clone() && (fold_info.clone() != None)) { + { + let fold_params = Rc::new(vec![ + make_param_node( + "acc".to_string(), + fold_acc_type.clone(), + None, + no_span(), + no_span(), + ), + make_param_node( + "elem".to_string(), + element_type.clone(), + None, + no_span(), + no_span(), + ), + ]); + let fold_callable = Rc::new(Node { + name: "".to_string(), + span: no_span(), + ident_span: None, + children: Rc::new(vec![]), + connective: Connective::NoConnective, + params: fold_params.clone(), + inferred: None, + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + transport: None, + properties: Rc::new(vec![]), + type_annotation: None, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }); + let lam_value = arg_value(a.clone()); + let prov_map = match (*elem_provenance.clone()).clone() { + SubValueRelation::SubValueUnknown => { + v2_rt::rc_empty_map::>() + } + _ => v2_rt::rc_map_insert( + v2_rt::rc_empty_map::>(), + "elem".to_string(), + elem_provenance.clone(), + ), + }; + let fold_scope = Rc::new(InferScope { + type_env: scope.type_env.clone(), + func_env: scope.func_env.clone(), + locals: scope.locals.clone(), + variant_collisions: scope.variant_collisions.clone(), + match_bound_names: scope.match_bound_names.clone(), + module_name: scope.module_name.clone(), + service_registry: scope.service_registry.clone(), + item_registry: scope.item_registry.clone(), + lambda_param_provenance: prov_map.clone(), + }); + let ar = infer_expr( + lam_value.clone(), + fold_scope.clone(), + Some(fold_callable.clone()), + ); + Rc::new(ArgInferResult { + typed_arg: make_arg_node( + arg_name_at( + a.clone(), + scope.type_env.clone().source_indices.clone(), + ), + ar.typed.clone(), + a.span.clone(), + a.span.clone(), + ), + diagnostics: ar.diagnostics.clone(), + }) + } + } else { + { + let nf_lam_value = arg_value(a.clone()); + let nf_prov_map = match (*elem_provenance.clone()).clone() { + SubValueRelation::SubValueUnknown => { + v2_rt::rc_empty_map::>() + } + _ => v2_rt::rc_map_insert( + v2_rt::rc_empty_map::>(), + "elem".to_string(), + elem_provenance.clone(), + ), + }; + let nf_scope = if is_lambda_expr(nf_lam_value.clone()) { + Rc::new(InferScope { + type_env: scope.type_env.clone(), + func_env: scope.func_env.clone(), + locals: scope.locals.clone(), + variant_collisions: scope.variant_collisions.clone(), + match_bound_names: scope.match_bound_names.clone(), + module_name: scope.module_name.clone(), + service_registry: scope.service_registry.clone(), + item_registry: scope.item_registry.clone(), + lambda_param_provenance: nf_prov_map.clone(), + }) + } else { + scope.clone() + }; + infer_arg_with_element_type( + a.clone(), + element_type.clone(), + nf_scope.clone(), + ) + } + } + } + }); + } + __result + }) + } +} + +pub fn is_lambda_expr(e: Rc) -> bool { + match (*e.expr_data.clone()).clone() { + ExprData::ExprLambda => true, + _ => false, + } +} + +pub fn seed_override_map() -> Rc>> { + Rc::new(vec!["".to_string()]).iter().cloned().fold( + v2_rt::rc_empty_map::>(), + |acc: Rc>>, k: String| { + v2_rt::rc_map_insert(acc, k.clone(), unit_type()) + }, + ) +} + +pub fn fold_override_map(key: String, value: Rc) -> Rc>> { + v2_rt::rc_map_insert(seed_override_map(), key, value) +} + +pub fn empty_override_map() -> Rc>> { + seed_override_map() +} + +pub fn infer_arg_with_element_type( + arg: Rc, + element_type: Rc, + scope: Rc, +) -> Rc { + { + let ar = infer_expr(arg_value(arg.clone()), scope.clone(), Some(element_type)); + Rc::new(ArgInferResult { + typed_arg: make_arg_node( + arg_name_at(arg.clone(), scope.type_env.clone().source_indices.clone()), + ar.typed.clone(), + arg.span.clone(), + arg.span.clone(), + ), + diagnostics: ar.diagnostics.clone(), + }) + } +} + +pub fn infer_expr( + texpr: Rc, + scope: Rc, + expected: Option>, +) -> Rc { + stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { + match (*texpr.expr_data.clone()).clone() { + ExprData::ExprLiteral { value: lit, .. } => { + let span = texpr.span.clone(); + let inferred_lit = match (*lit.clone()).clone() { + LiteralValue::LitNull => infer_null_literal_node(expected.clone()), + _ => infer_literal_node(lit.clone()), + }; + ok_infer(make_expr_node( + Rc::new(ExprData::ExprLiteral { value: lit.clone() }), + Rc::new(vec![]), + Some(Rc::new(InferredNode::Resolved { node: inferred_lit })), + span.clone(), + )) + } + ExprData::ExprError { kind, message, .. } => { + let span = texpr.span.clone(); + Rc::new(InferResult { + typed: make_expr_error_node(kind.clone(), message.clone(), span.clone()), + diagnostics: Rc::new(vec![]), + }) + } + ExprData::ExprVar { + binding_kind: _, .. + } => { + let name = + expr_var_name_at(texpr.clone(), scope.type_env.clone().source_indices.clone()); + let span = texpr.span.clone(); + let collision = v2_rt::map_get(&scope.variant_collisions.clone(), name.clone()); + if (collision.clone() != None) { + variant_collision_result(name.clone(), span.clone(), collision.clone().unwrap()) + } else { + match v2_rt::map_get(&scope.locals.clone(), name.clone()) { + Some(binding) => { + let binding_kind = infer_var_binding_kind(scope.clone(), name.clone()); + let local_typed = make_named_expr_node( + name.clone(), + Rc::new(ExprData::ExprVar { + binding_kind: Some(binding_kind), + }), + Rc::new(vec![]), + Some(Rc::new(InferredNode::Resolved { + node: binding.resolved.clone(), + })), + span.clone(), + span.clone(), + ); + let expected_local_diags = match expected.clone() { + Some(expected_node) => { + if rejects_string_for_optional_coproduct_field( + expected_node.clone(), + binding.resolved.clone(), + scope.type_env.clone().source_indices.clone(), + ) { + Rc::new(vec![type_mismatch_error( + node_type_shape( + expected_node.clone(), + scope.type_env.clone().source_indices.clone(), + ), + node_type_shape( + binding.resolved.clone(), + scope.type_env.clone().source_indices.clone(), + ), + span.clone(), + scope.module_name.clone(), + )]) + } else { + Rc::new(vec![]) + } + } + None => Rc::new(vec![]), + }; + Rc::new(InferResult { + typed: local_typed, + diagnostics: expected_local_diags, + }) + } + None => { + let expected_variant_parent = match expected.clone() { + Some(expected_node) => match expected_coproduct_variant( + expected_node.clone(), + name.clone(), + scope.type_env.clone().source_indices.clone(), + ) { + Some(_) => Some(authored_name_at( + scope.type_env.clone().source_indices.clone(), + expected_node.clone(), + )), + None => None, + }, + None => None, + }; + match expected_variant_parent { + Some(parent_enum) => ok_infer(make_named_expr_node( + name.clone(), + Rc::new(ExprData::ExprVar { + binding_kind: Some(Rc::new( + VarBindingKind::VariantValueBinding { + parent_enum: parent_enum.clone(), + }, + )), + }), + Rc::new(vec![]), + Some(Rc::new(InferredNode::Resolved { + node: expected.clone().unwrap(), + })), + span.clone(), + span.clone(), + )), + None => match lookup_func_sig(scope.func_env.clone(), name.clone()) + { + Some(fsig) => { + if ((fsig.params.clone().len() as i64) == 0) { + ok_infer(make_named_expr_node( + name.clone(), + Rc::new(ExprData::ExprCall { + call_semantics: Some( + CallSemantics::PlainCallSemantics, + ), + descent_evidence: None, + }), + Rc::new(vec![]), + Some(Rc::new(InferredNode::Resolved { + node: fsig.inferred.clone(), + })), + span.clone(), + span.clone(), + )) + } else { + ok_infer(make_named_expr_node( + name.clone(), + Rc::new(ExprData::ExprVar { + binding_kind: Some(Rc::new( + VarBindingKind::FunctionValueBinding, + )), + }), + Rc::new(vec![]), + Some(Rc::new(InferredNode::Resolved { + node: resolved_callable_type( + fsig.params.clone(), + fsig.inferred.clone(), + ), + })), + span.clone(), + span.clone(), + )) + } + } + None => { + let err_texpr = make_named_expr_node( + name.clone(), + Rc::new(ExprData::ExprVar { binding_kind: None }), + Rc::new(vec![]), + Some(Rc::new(InferredNode::Resolved { + node: error_type(), + })), + span.clone(), + span.clone(), + ); + Rc::new(InferResult { + typed: err_texpr, + diagnostics: Rc::new(vec![inference_error( + v2_rt::concat( + v2_rt::concat( + "undefined variable '".to_string(), + name.clone(), + ), + "'".to_string(), + ), + span.clone(), + scope.module_name.clone(), + )]), + }) + } + }, + } + } + } + } + } + ExprData::ExprFieldAccess { summary: _, .. } => { + let field_name = field_access_field_at( + texpr.clone(), + scope.type_env.clone().source_indices.clone(), + ); + let span = texpr.span.clone(); + let base_expr = field_access_base(texpr.clone()); + let base_result = infer_expr(base_expr, scope.clone(), None); + let base_typed = base_result.typed.clone(); + let base_diags = base_result.diagnostics.clone(); + let base_rt = resolved_type(base_typed.clone()); + let resolved_base = + resolve_scrutinee_type_node(scope.type_env.clone(), base_rt.clone()); + let resolved_base_is_error = if (resolved_base.inferred.clone() != None) { + is_compiler_error(resolved_base.inferred.clone().clone().unwrap()) + } else { + false + }; + if resolved_base_is_error { + Rc::new(InferResult { + typed: make_expr_error_node( + ExprErrorKind::SemanticExprError, + "error type cascade".to_string(), + span.clone(), + ), + diagnostics: base_diags, + }) + } else { + match lookup_field_type_node( + resolved_base.clone(), + field_name.clone(), + scope.type_env.clone().source_indices.clone(), + ) { + Some(field_type) => { + let field_summary = field_summary_for_type( + base_rt.clone(), + scope.type_env.clone(), + field_name.clone(), + ); + let fa_texpr = make_named_expr_node( + field_name.clone(), + Rc::new(ExprData::ExprFieldAccess { + summary: field_summary, + }), + Rc::new(vec![base_typed.clone()]), + Some(Rc::new(InferredNode::Resolved { + node: field_type.clone(), + })), + span.clone(), + node_name_span(texpr.clone()), + ); + Rc::new(InferResult { + typed: fa_texpr, + diagnostics: base_diags, + }) + } + None => { + let base_is_type_var = if (resolved_base.inferred.clone() != None) { + is_type_variable(resolved_base.inferred.clone().clone().unwrap()) + } else { + false + }; + if base_is_type_var { + { + let fa_texpr = make_named_expr_node( + field_name.clone(), + Rc::new(ExprData::ExprFieldAccess { + summary: Some(Rc::new(FieldSummary { + access_style: FieldAccessStyle::StoredField, + value_shape: FieldValueShape::PlainValue, + })), + }), + Rc::new(vec![base_typed.clone()]), + Some(Rc::new(InferredNode::TypeVariable { + id: "field_of_type_var".to_string(), + })), + span.clone(), + node_name_span(texpr.clone()), + ); + Rc::new(InferResult { + typed: fa_texpr, + diagnostics: base_diags, + }) + } + } else { + match check_service_field_access_node( + base_rt.clone(), + field_name.clone(), + scope.service_registry.clone(), + scope.type_env.clone().source_indices.clone(), + ) { + Some(svc_type) => { + let fa_texpr = make_named_expr_node( + field_name.clone(), + Rc::new(ExprData::ExprFieldAccess { + summary: Some(Rc::new(FieldSummary { + access_style: FieldAccessStyle::StoredField, + value_shape: FieldValueShape::PlainValue, + })), + }), + Rc::new(vec![base_typed.clone()]), + Some(Rc::new(InferredNode::Resolved { + node: svc_type.clone(), + })), + span.clone(), + node_name_span(texpr.clone()), + ); + Rc::new(InferResult { + typed: fa_texpr, + diagnostics: base_diags, + }) + } + None => { + let error_message = v2_rt::concat( + v2_rt::concat( + v2_rt::concat( + v2_rt::concat( + "no field '".to_string(), + field_name.clone(), + ), + "' on type '".to_string(), + ), + authored_name_at( + scope.type_env.clone().source_indices.clone(), + resolved_base.clone(), + ), + ), + "'".to_string(), + ); + let fa_texpr = make_expr_error_node( + ExprErrorKind::SemanticExprError, + error_message.clone(), + span.clone(), + ); + Rc::new(InferResult { + typed: fa_texpr, + diagnostics: v2_rt::concat( + base_diags, + Rc::new(vec![inference_error( + error_message.clone(), + span.clone(), + scope.module_name.clone(), + )]), + ), + }) + } + } + } + } + } + } + } + ExprData::ExprCall { .. } => { + let func_name = + expr_call_func_at(texpr.clone(), scope.type_env.clone().source_indices.clone()); + let span = texpr.span.clone(); + let call_args = texpr.children.clone(); + let sig = lookup_func_sig(scope.func_env.clone(), func_name.clone()); + let sig_params = match sig.clone() { + Some(s) => s.params.clone(), + None => Rc::new(vec![]), + }; + let generic_names = Rc::new({ + let mut __result = Vec::new(); + for p in Rc::new({ + let mut __result = Vec::new(); + for p in sig_params.clone().iter().cloned() { + if param_is_generic_decl( + p.clone(), + scope.type_env.clone().source_indices.clone(), + ) { + __result.push(p); + } + } + __result + }) + .iter() + .cloned() + { + __result.push(authored_name_at( + scope.type_env.clone().source_indices.clone(), + param_node_type_expr(p.clone()), + )); + } + __result + }); + let has_lambda = { + let mut __found = false; + for a in call_args.clone().iter().cloned() { + if is_lambda_expr(arg_value(a.clone())) { + __found = true; + break; + } + } + __found + }; + let call_method_args = Rc::new( + call_args + .clone() + .iter() + .cloned() + .skip(1 as usize) + .collect::>(), + ); + let call_method_name = Some(func_name.clone()); + let call_fold_info = extract_fold_init_info( + call_method_name.clone(), + call_method_args.clone(), + 2, + scope.clone(), + expected.clone(), + ); + let call_fold_acc_type = match call_fold_info.clone() { + Some(fi) => resolved_type(arg_value(fi.typed_arg.clone())), + None => error_type(), + }; + let arg_call = if ((has_lambda && ((call_args.clone().len() as i64) >= 2)) + && (sig.clone() == None)) + { + Rc::new(ArgGenericFoldState { + subst: v2_rt::rc_empty_map::>(), results: match call_args.clone().first().cloned() { Some(first_arg) => { let first_result = @@ -2806,30 +3766,6 @@ pub fn infer_expr( } __result }); - let generic_names = Rc::new({ - let mut __result = Vec::new(); - for p in Rc::new({ - let mut __result = Vec::new(); - for p in sig_params.clone().iter().cloned() { - if param_is_generic_decl( - p.clone(), - scope.type_env.clone().source_indices.clone(), - ) { - __result.push(p); - } - } - __result - }) - .iter() - .cloned() - { - __result.push(authored_name_at( - scope.type_env.clone().source_indices.clone(), - param_node_type_expr(p.clone()), - )); - } - __result - }); let final_state = Rc::new( call_args .clone() @@ -2956,6 +3892,7 @@ pub fn infer_expr( value_params_for_check, typed_args.clone(), call_subst.clone(), + generic_names.clone(), scope.type_env.clone(), scope.module_name.clone(), ) @@ -3028,7 +3965,11 @@ pub fn infer_expr( scope.type_env.clone().source_indices.clone(), ); let is_known_method = (method_resolution.result_type.clone() != None); - if (is_known_method && ((typed_args.clone().len() as i64) > 0)) { + let is_builtin_function = + (infer_builtin_call_type(func_name.clone()) != None); + if ((is_known_method && ((typed_args.clone().len() as i64) > 0)) + && !is_builtin_function.clone()) + { { let receiver = method_receiver.clone(); let remaining = Rc::new( @@ -3171,6 +4112,7 @@ pub fn infer_expr( match_pattern: receiver.match_pattern.clone(), expr_data: receiver.expr_data.clone(), ident: None, + binding_id: None, }) } else { receiver.clone() @@ -3345,7 +4287,7 @@ match bare_s { } } } else { - if (infer_builtin_call_type(func_name.clone()) != None) { + if is_builtin_function.clone() { { let tier2b = infer_tier2b_builtin_with_kernel_diags( func_name.clone(), @@ -3424,40 +4366,46 @@ match bare_s { }) } } else { - match infer_variant_constructor_call( - func_name.clone(), - call_args.clone(), - span.clone(), - node_name_span(texpr.clone()), - scope.clone(), - ) { - Some(ctor_result) => ctor_result.clone(), - None => { - let type_match = lookup_type_by_name( - scope.type_env.clone(), + { + let collision = v2_rt::map_get( + &scope.variant_collisions.clone(), + func_name.clone(), + ); + if (collision.clone() != None) { + variant_collision_result( func_name.clone(), - ); - let resolved_type = match type_match.clone() + span.clone(), + collision.clone().unwrap(), + ) + } else { { - Some(tn) => tn.clone(), - None => error_type(), - }; - let call_diags = match type_match.clone() { - Some(_) => Rc::new(vec![]), - None => Rc::new(vec![inference_error( - v2_rt::concat( - v2_rt::concat( - "function '".to_string(), - func_name.clone(), - ), - "' not found in scope" - .to_string(), - ), - span.clone(), - scope.module_name.clone(), - )]), - }; - Rc::new(InferResult { + let ctor = + infer_variant_constructor_call( + func_name.clone(), + call_args.clone(), + span.clone(), + node_name_span(texpr.clone()), + scope.clone(), + ); + if (ctor.clone() != None) { + ctor.clone().unwrap() + } else { + { + let type_match = + lookup_type_by_name( + scope.type_env.clone(), + func_name.clone(), + ); + let resolved_type = + match type_match.clone() { + Some(tn) => tn.clone(), + None => error_type(), + }; + let call_diags = match type_match.clone() { + Some(_) => Rc::new(vec![]), + None => Rc::new(vec![inference_error(v2_rt::concat(v2_rt::concat("function '".to_string(), func_name.clone()), "' not found in scope".to_string()), span.clone(), scope.module_name.clone())]), +}; + Rc::new(InferResult { typed: make_named_expr_node(func_name.clone(), Rc::new(ExprData::ExprCall { call_semantics: Some(CallSemantics::PlainCallSemantics), descent_evidence: None, @@ -3466,6 +4414,9 @@ match bare_s { })), span.clone(), node_name_span(texpr.clone())), diagnostics: v2_rt::concat(arg_diags, call_diags), }) + } + } + } } } } @@ -4013,15 +4964,58 @@ match bare_s { let else_diags = else_result.diagnostics.clone(); let then_rt = resolved_type(then_typed.clone()); let else_rt = resolved_type(else_typed.clone()); - let unified = prefer_specific_type( + let then_is_none = direct_call_actual_is_none( + then_expr.clone(), then_rt.clone(), + scope.type_env.clone().source_indices.clone(), + ); + let else_is_none = direct_call_actual_is_none( + else_branch.clone(), else_rt.clone(), scope.type_env.clone().source_indices.clone(), ); - let branch_diags = if node_type_compatible( + let then_compare_raw = + direct_call_arg_decl_identity(then_rt.clone(), scope.type_env.clone()); + let else_compare_raw = + direct_call_arg_decl_identity(else_rt.clone(), scope.type_env.clone()); + let then_compare_stamped = stamp_hidden_dependency_refs( + then_compare_raw, + scope.type_env.clone(), + scope.type_env.clone().source_indices.clone(), + ); + let else_compare_stamped = stamp_hidden_dependency_refs( + else_compare_raw, + scope.type_env.clone(), + scope.type_env.clone().source_indices.clone(), + ); + let then_compare = if (else_is_none.clone() && !then_is_none.clone()) { + with_optional_cardinality(then_compare_stamped) + } else { + then_compare_stamped + }; + let else_compare = if (then_is_none.clone() && !else_is_none.clone()) { + with_optional_cardinality(else_compare_stamped) + } else { + else_compare_stamped + }; + let unified_raw = prefer_specific_type( then_rt.clone(), else_rt.clone(), scope.type_env.clone().source_indices.clone(), + ); + let unified = if (then_is_none.clone() && !else_is_none.clone()) { + with_optional_cardinality(else_rt.clone()) + } else { + if (else_is_none.clone() && !then_is_none.clone()) { + with_optional_cardinality(then_rt.clone()) + } else { + unified_raw + } + }; + let branch_diags = if node_type_compatible( + then_compare, + else_compare, + scope.type_env.clone().source_indices.clone(), ) { Rc::new(vec![]) } else { @@ -4162,6 +5156,7 @@ match bare_s { span.clone(), node_name_span(texpr.clone()), scope.clone(), + expected.clone(), ) } ExprData::ExprListLit => { @@ -4174,7 +5169,13 @@ match bare_s { scope.type_env.clone().source_indices.clone(), ) { match exp.children.clone().first().cloned() { - Some(elem) => Some(child_type_node(elem.clone())), + Some(elem) => { + let child = child_type_node(elem.clone()); + match lookup_type_for(scope.type_env.clone(), child.clone()) { + Some(resolved_child) => Some(resolved_child.clone()), + None => Some(child.clone()), + } + } None => None, } } else { @@ -4205,9 +5206,12 @@ match bare_s { __result }); let elem_type_node = if ((elem_results.clone().len() as i64) > 0) { - match elem_results.clone().first().cloned() { - Some(r) => resolved_type(r.typed.clone()), - None => unit_type(), + match elem_expected.clone() { + Some(expected_elem) => expected_elem.clone(), + None => match elem_results.clone().first().cloned() { + Some(r) => resolved_type(r.typed.clone()), + None => unit_type(), + }, } } else { match expected.clone() { @@ -4465,6 +5469,7 @@ match bare_s { func_env: lam_scope.func_env.clone(), locals: lam_scope.locals.clone(), match_bound_names: lam_scope.match_bound_names.clone(), + variant_collisions: lam_scope.variant_collisions.clone(), module_name: lam_scope.module_name.clone(), service_registry: lam_scope.service_registry.clone(), item_registry: lam_scope.item_registry.clone(), @@ -4520,6 +5525,7 @@ match bare_s { has_non_tail_self_call: pn.has_non_tail_self_call.clone(), match_pattern: pn.match_pattern.clone(), expr_data: pn.expr_data.clone(), + binding_id: None, }) }); } @@ -4925,6 +5931,7 @@ pub fn infer_variant_constructor_call( span.clone(), name_span, scope.clone(), + None, )) } }, @@ -4971,9 +5978,11 @@ pub fn infer_record_lit( span: Rc, name_span: Rc, scope: Rc, + expected: Option>, ) -> Rc { { - let struct_fields = record_lit_expected_fields(type_name.clone(), scope.clone()); + let struct_fields = + record_lit_expected_fields(type_name.clone(), scope.clone(), expected.clone()); let fi_infer_results = Rc::new({ let mut __result = Vec::new(); for fi in field_inits.iter().cloned() { @@ -5020,14 +6029,35 @@ pub fn infer_record_lit( let field_type_diags = match field_expected.clone() { Some(expected_node) => { let got_node = resolved_type(ar_typed.clone()); - if rejects_string_for_optional_coproduct_field( - expected_node.clone(), - got_node.clone(), - scope.type_env.clone().source_indices.clone(), - ) { + let expected_decl = + lookup_type_for(scope.type_env.clone(), expected_node.clone()); + let expected_diag_node = match expected_decl.clone() { + Some(decl_node) => decl_node.clone(), + None => expected_node.clone(), + }; + let string_optional_reject = + rejects_string_for_optional_coproduct_field( + expected_node.clone(), + got_node.clone(), + scope.type_env.clone().source_indices.clone(), + ); + let got_is_string = + (got_node.name.clone().as_str() == "String".to_string().as_str()); + let named_optional_coproduct_string_reject = + match expected_node.return_cardinality.clone() { + Cardinality::CardOptional => match got_is_string.clone() { + true => { + (expected_diag_node.connective.clone() + == Connective::Disj) + } + false => false, + }, + _ => false, + }; + if string_optional_reject.clone() { Rc::new(vec![type_mismatch_error( node_type_shape( - expected_node.clone(), + expected_diag_node.clone(), scope.type_env.clone().source_indices.clone(), ), node_type_shape( @@ -5038,7 +6068,22 @@ pub fn infer_record_lit( scope.module_name.clone(), )]) } else { - Rc::new(vec![]) + if named_optional_coproduct_string_reject.clone() { + Rc::new(vec![type_mismatch_error( + node_type_shape( + expected_diag_node.clone(), + scope.type_env.clone().source_indices.clone(), + ), + node_type_shape( + got_node.clone(), + scope.type_env.clone().source_indices.clone(), + ), + ar_typed.span.clone(), + scope.module_name.clone(), + )]) + } else { + Rc::new(vec![]) + } } } None => Rc::new(vec![]), @@ -5071,158 +6116,232 @@ pub fn infer_record_lit( } __result }); - if (type_name.clone() == None) { + if ((type_name.clone() != None) + && (v2_rt::map_get( + &scope.variant_collisions.clone(), + type_name.clone().unwrap(), + ) != None)) + { { - let child_nodes = Rc::new({ - let mut __result = Vec::new(); - for fir in fi_infer_results.clone().iter().cloned() { - __result.push(Rc::new(Node { - name: field_init_node_name_at( - fir.typed_field.clone(), - scope.type_env.clone().source_indices.clone(), - ), - span: fir.typed_field.clone().span.clone(), - ident_span: fir.typed_field.clone().ident_span.clone(), - children: Rc::new(vec![]), - connective: Connective::NoConnective, - params: Rc::new(vec![]), - inferred: fir.infer_result.clone().typed.clone().inferred.clone(), - return_cardinality: Cardinality::Required, - uses: Rc::new(vec![]), - body: None, - transport: None, - properties: Rc::new(vec![]), - type_annotation: None, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - })); - } - __result - }); - let anon_node = Rc::new(Node { - name: "".to_string(), - span: no_span(), - ident_span: None, - children: child_nodes, - connective: Connective::Conj, - params: Rc::new(vec![]), - inferred: None, - return_cardinality: Cardinality::Required, - uses: Rc::new(vec![]), - body: None, - transport: None, - properties: Rc::new(vec![]), - type_annotation: None, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }); - let typed_field_nodes = typed_fields; - let texpr = make_expr_node( + let collision = v2_rt::map_get( + &scope.variant_collisions.clone(), + type_name.clone().unwrap(), + ) + .clone() + .unwrap(); + let texpr = make_named_expr_node( + type_name.clone().unwrap(), Rc::new(ExprData::ExprRecordLit { parent_enum: None }), - typed_field_nodes, - Some(Rc::new(InferredNode::Resolved { node: anon_node })), + typed_fields, + Some(Rc::new(InferredNode::Resolved { node: error_type() })), span.clone(), + name_span, ); Rc::new(InferResult { typed: texpr, - diagnostics: fi_diags, + diagnostics: v2_rt::concat(fi_diags, Rc::new(vec![collision])), }) } } else { - { - let type_lookup = - lookup_type_by_name(scope.type_env.clone(), type_name.clone().unwrap()); - let local_variant_parent = - lookup_variant_parent_enum(scope.clone(), type_name.clone().unwrap()); - let effective_lookup = match type_lookup.clone() { - Some(_) => type_lookup.clone(), - None => { - let local_lookup = - lookup_in_scope(scope.locals.clone(), type_name.clone().unwrap()); - match local_lookup { - Some(local_node) => { - lookup_type_for(scope.type_env.clone(), local_node.clone()) - } - None => None, - } - } - }; - let raw_resolved = match effective_lookup.clone() { - Some(tn) => tn.clone(), - None => error_type(), - }; - let expected_optional_parent = Some("Optional".to_string()); - let is_present_ctor = ((type_name.clone().unwrap().as_str() - == "Present".to_string().as_str()) - && (local_variant_parent.clone().as_deref() - == expected_optional_parent.as_deref())); - let resolved_node = if is_present_ctor { - { - let val_field = Rc::new({ - let mut __result = Vec::new(); - for fir in fi_infer_results.clone().iter().cloned() { - if (field_init_node_name_at( + if (type_name.clone() == None) { + { + let child_nodes = Rc::new({ + let mut __result = Vec::new(); + for fir in fi_infer_results.clone().iter().cloned() { + __result.push(Rc::new(Node { + name: field_init_node_name_at( fir.typed_field.clone(), scope.type_env.clone().source_indices.clone(), - ) - .as_str() - == "value".to_string().as_str()) - { - __result.push(fir); + ), + span: fir.typed_field.clone().span.clone(), + ident_span: fir.typed_field.clone().ident_span.clone(), + children: Rc::new(vec![]), + connective: Connective::NoConnective, + params: Rc::new(vec![]), + inferred: fir.infer_result.clone().typed.clone().inferred.clone(), + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + transport: None, + properties: Rc::new(vec![]), + type_annotation: None, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + })); + } + __result + }); + let anon_node = Rc::new(Node { + name: "".to_string(), + span: no_span(), + ident_span: None, + children: child_nodes, + connective: Connective::Conj, + params: Rc::new(vec![]), + inferred: None, + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + transport: None, + properties: Rc::new(vec![]), + type_annotation: None, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }); + let typed_field_nodes = typed_fields; + let texpr = make_expr_node( + Rc::new(ExprData::ExprRecordLit { parent_enum: None }), + typed_field_nodes, + Some(Rc::new(InferredNode::Resolved { node: anon_node })), + span.clone(), + ); + Rc::new(InferResult { + typed: texpr, + diagnostics: fi_diags, + }) + } + } else { + { + let type_lookup = + lookup_type_by_name(scope.type_env.clone(), type_name.clone().unwrap()); + let local_variant_parent = + lookup_variant_parent_enum(scope.clone(), type_name.clone().unwrap()); + let expected_variant_parent = match expected.clone() { + Some(expected_node) => match expected_coproduct_variant( + expected_node.clone(), + type_name.clone().unwrap(), + scope.type_env.clone().source_indices.clone(), + ) { + Some(_) => Some(authored_name_at( + scope.type_env.clone().source_indices.clone(), + expected_node.clone(), + )), + None => None, + }, + None => None, + }; + let env_variant_parent = match lookup_coproduct_parent_binding_by_variant( + scope.type_env.clone(), + type_name.clone().unwrap(), + ) { + Some(parent_binding) => Some(parent_binding.name.clone()), + None => None, + }; + let effective_variant_parent = match local_variant_parent.clone() { + Some(_) => local_variant_parent.clone(), + None => match env_variant_parent.clone() { + Some(_) => env_variant_parent.clone(), + None => expected_variant_parent, + }, + }; + let effective_lookup = match type_lookup.clone() { + Some(_) => type_lookup.clone(), + None => { + let local_lookup = + lookup_in_scope(scope.locals.clone(), type_name.clone().unwrap()); + match local_lookup { + Some(local_node) => { + lookup_type_for(scope.type_env.clone(), local_node.clone()) } + None => match lookup_coproduct_parent_binding_by_variant( + scope.type_env.clone(), + type_name.clone().unwrap(), + ) { + Some(parent_binding) => Some(parent_binding.resolved.clone()), + None => match expected.clone() { + Some(expected_node) => match expected_coproduct_variant( + expected_node.clone(), + type_name.clone().unwrap(), + scope.type_env.clone().source_indices.clone(), + ) { + Some(_) => Some(expected_node.clone()), + None => None, + }, + None => None, + }, + }, } - __result - }) - .first() - .cloned(); - match val_field { - Some(val_fir) => with_optional_cardinality(resolved_type( - val_fir.infer_result.clone().typed.clone(), - )), - None => raw_resolved, } - } - } else { - raw_resolved - }; - let type_diags = match effective_lookup.clone() { - Some(_) => Rc::new(vec![]), - None => Rc::new(vec![inference_error( - v2_rt::concat( - v2_rt::concat("type '".to_string(), type_name.clone().unwrap()), - "' not found in scope".to_string(), - ), - span.clone(), - scope.module_name.clone(), - )]), - }; - let typed_field_nodes2 = typed_fields; - let rl_name = match type_name.clone() { - Some(tn_val) => tn_val.clone(), - None => "".to_string(), - }; - let texpr = make_named_expr_node( - rl_name, - Rc::new(ExprData::ExprRecordLit { - parent_enum: local_variant_parent.clone(), - }), - typed_field_nodes2, - Some(Rc::new(InferredNode::Resolved { - node: resolved_node, - })), - span.clone(), - name_span, - ); - Rc::new(InferResult { - typed: texpr, - diagnostics: v2_rt::concat(fi_diags, type_diags), - }) + }; + let raw_resolved = match effective_lookup.clone() { + Some(tn) => tn.clone(), + None => error_type(), + }; + let expected_optional_parent = Some("Optional".to_string()); + let is_present_ctor = ((type_name.clone().unwrap().as_str() + == "Present".to_string().as_str()) + && (effective_variant_parent.clone().as_deref() + == expected_optional_parent.as_deref())); + let resolved_node = if is_present_ctor { + { + let val_field = Rc::new({ + let mut __result = Vec::new(); + for fir in fi_infer_results.clone().iter().cloned() { + if (field_init_node_name_at( + fir.typed_field.clone(), + scope.type_env.clone().source_indices.clone(), + ) + .as_str() + == "value".to_string().as_str()) + { + __result.push(fir); + } + } + __result + }) + .first() + .cloned(); + match val_field { + Some(val_fir) => with_optional_cardinality(resolved_type( + val_fir.infer_result.clone().typed.clone(), + )), + None => raw_resolved, + } + } + } else { + raw_resolved + }; + let type_diags = match effective_lookup.clone() { + Some(_) => Rc::new(vec![]), + None => Rc::new(vec![inference_error( + v2_rt::concat( + v2_rt::concat("type '".to_string(), type_name.clone().unwrap()), + "' not found in scope".to_string(), + ), + span.clone(), + scope.module_name.clone(), + )]), + }; + let typed_field_nodes2 = typed_fields; + let rl_name = match type_name.clone() { + Some(tn_val) => tn_val.clone(), + None => "".to_string(), + }; + let texpr = make_named_expr_node( + rl_name, + Rc::new(ExprData::ExprRecordLit { + parent_enum: effective_variant_parent.clone(), + }), + typed_field_nodes2, + Some(Rc::new(InferredNode::Resolved { + node: resolved_node, + })), + span.clone(), + name_span, + ); + Rc::new(InferResult { + typed: texpr, + diagnostics: v2_rt::concat(fi_diags, type_diags), + }) + } } } } @@ -6537,8 +7656,10 @@ pub fn classify_call_via_provenance( ); Rc::new(v2_rt::map_keys(¶m_map)).iter().cloned().fold( None, - |result: _, callee_pname: String| match v2_rt::map_get(¶m_map, callee_pname.clone()) - { + |result: Option>, callee_pname: String| match v2_rt::map_get( + ¶m_map, + callee_pname.clone(), + ) { Some(callee_rel) => match v2_rt::map_get(&arg_by_name, callee_pname.clone()) { Some(arg_expr) => { let arg_rel = classify_call_arg_provenance(arg_expr.clone(), ctx.clone()); @@ -7370,6 +8491,7 @@ pub fn annotate_descent(body: Rc, ctx: Rc) -> Rc { descent_evidence: Some(evidence), }), ident: None, + binding_id: None, }) } ExprData::ExprMatch => { @@ -7660,6 +8782,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota match_pattern: body.match_pattern.clone(), expr_data: body.expr_data.clone(), ident: None, + binding_id: None, }) } ExprData::ExprLet => { @@ -7768,6 +8891,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota match_pattern: body.match_pattern.clone(), expr_data: body.expr_data.clone(), ident: None, + binding_id: None, }) } ExprData::ExprBlock => { @@ -7893,6 +9017,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota match_pattern: body.match_pattern.clone(), expr_data: body.expr_data.clone(), ident: None, + binding_id: None, }) } ExprData::ExprMethodCall { @@ -8160,6 +9285,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota match_pattern: body.match_pattern.clone(), expr_data: body.expr_data.clone(), ident: None, + binding_id: None, }) } } else { @@ -8229,6 +9355,7 @@ make_arm_node(arm_pattern(arm_node.clone()), arm_guard(arm_node.clone()), annota match_pattern: body.match_pattern.clone(), expr_data: body.expr_data.clone(), ident: None, + binding_id: None, }) } _ => map_children(body.clone(), |child| { @@ -9584,1050 +10711,1973 @@ if ((Rc::new(v2_rt::map_keys(&composed_field_map)).len() as i64) > 0) { ); v2_rt::rc_map_insert(lp.clone(), bname.clone(), vprov.clone()) } - _ => lp.clone(), - }, - ); - match stmts - .clone() - .get((stmt_count.clone() - 1) as usize) - .cloned() - { - Some(last) => collect_variant_constructors( - last.clone(), - parent_enum.clone(), - param_names.clone(), - param_types.clone(), - type_env.clone(), - func_sigs.clone(), - final_lp, - acc.clone(), - ), - None => acc.clone(), + _ => lp.clone(), + }, + ); + match stmts + .clone() + .get((stmt_count.clone() - 1) as usize) + .cloned() + { + Some(last) => collect_variant_constructors( + last.clone(), + parent_enum.clone(), + param_names.clone(), + param_types.clone(), + type_env.clone(), + func_sigs.clone(), + final_lp, + acc.clone(), + ), + None => acc.clone(), + } + } + } + } + _ => acc.clone(), + } + }) +} + +pub fn merge_field_prov_maps( + a: Rc>>>>, + b: Rc>>>>, +) -> Rc>>>> { + { + let from_a = Rc::new(v2_rt::map_keys(&a)).iter().cloned().fold( + v2_rt::rc_empty_map::>>>(), + |result: Rc>>>>, + fname: String| match v2_rt::map_get(&a, fname.clone()) { + Some(a_prov) => match v2_rt::map_get(&b, fname.clone()) { + Some(b_prov) => v2_rt::rc_map_insert( + result.clone(), + fname.clone(), + union_prov_maps(a_prov.clone(), b_prov.clone()), + ), + None => v2_rt::rc_map_insert(result.clone(), fname.clone(), a_prov.clone()), + }, + None => result.clone(), + }, + ); + Rc::new(v2_rt::map_keys(&b)).iter().cloned().fold( + from_a, + |result: Rc>>>>, + fname: String| { + if (v2_rt::map_get(&result, fname.clone()) != None) { + result.clone() + } else { + match v2_rt::map_get(&b, fname.clone()) { + Some(b_prov) => { + v2_rt::rc_map_insert(result.clone(), fname.clone(), b_prov.clone()) + } + None => result.clone(), + } + } + }, + ) + } +} + +pub fn union_prov_maps( + a: Rc>>, + b: Rc>>, +) -> Rc>> { + { + let from_a = Rc::new(v2_rt::map_keys(&a)).iter().cloned().fold( + empty_prov_map(), + |result: Rc>>, key: String| match v2_rt::map_get( + &a, + key.clone(), + ) { + Some(a_rel) => match v2_rt::map_get(&b, key.clone()) { + Some(b_rel) => v2_rt::rc_map_insert( + result.clone(), + key.clone(), + join_sub_value(a_rel.clone(), b_rel.clone()), + ), + None => v2_rt::rc_map_insert(result.clone(), key.clone(), a_rel.clone()), + }, + None => result.clone(), + }, + ); + Rc::new(v2_rt::map_keys(&b)).iter().cloned().fold( + from_a, + |result: Rc>>, key: String| { + if (v2_rt::map_get(&result, key.clone()) != None) { + result.clone() + } else { + match v2_rt::map_get(&b, key.clone()) { + Some(b_rel) => { + v2_rt::rc_map_insert(result.clone(), key.clone(), b_rel.clone()) + } + None => result.clone(), + } + } + }, + ) + } +} + +pub fn populate_output_provenance( + typed_items: Rc>>, + func_env: Rc, + type_env: Rc, + locals: Rc>>, +) -> Rc { + { + let updated_sigs = typed_items.iter().cloned().fold( + func_env.signatures.clone(), + |acc: Rc>>, item: Rc| { + if ((item.params.clone().len() as i64) > 0) { + { + let fn_name = + authored_name_at(type_env.source_indices.clone(), item.clone()); + if (is_child_accessor_in_model(fn_name.clone()) + || is_tree_size_reducing(fn_name.clone())) + { + match item.params.clone().first().cloned() { + Some(first_param) => { + let pname = param_node_name_at( + first_param.clone(), + type_env.source_indices.clone(), + ); + let ptype = resolved_type_name( + first_param.clone(), + type_env.source_indices.clone(), + ); + if ((ptype.clone().as_str() != "".to_string().as_str()) + && (pname.clone().as_str() != "".to_string().as_str())) + { + { + let fields = inductive_fields_for( + type_env.clone(), + ptype.clone(), + ); + let list_field = Rc::new({ + let mut __result = Vec::new(); + for f in fields.clone().iter().cloned() { + if match f.shape.clone() { + RecursionShape::ListRecursion => true, + _ => false, + } { + __result.push(f); + } + } + __result + }) + .first() + .cloned(); + match list_field.clone() { + Some(ind_field) => { + let relation = + Rc::new(SubValueRelation::StrictSubValue { + field: ind_field.clone(), + factor: Rc::new( + ShrinkFactor::UnitShrink, + ), + }); + let provenance = + Rc::new(vec![v2_rt::rc_map_insert( + v2_rt::rc_empty_map::< + String, + Rc, + >( + ), + pname.clone(), + relation.clone(), + )]); + match v2_rt::map_get(&acc, fn_name.clone()) { + Some(sig) => v2_rt::rc_map_insert( + acc.clone(), + fn_name.clone(), + Rc::new(ResolvedFuncSig { + name: sig.name.clone(), + params: sig.params.clone(), + inferred: sig.inferred.clone(), + is_async: sig.is_async.clone(), + output_provenance: provenance + .clone(), + variant_provenance: sig + .variant_provenance + .clone(), + }), + ), + None => acc.clone(), + } + } + None => acc.clone(), + } + } + } else { + acc.clone() + } + } + None => acc.clone(), + } + } else { + match item.body.clone() { + Some(body) => { + if !expr_has_self_call( + body.clone(), + fn_name.clone(), + type_env.source_indices.clone(), + ) { + { + let provenance = infer_output_provenance( + body.clone(), + item.params.clone(), + type_env.clone(), + locals.clone(), + acc.clone(), + ); + let variant_prov = + match item.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { + node: rt, + .. + }) => compute_variant_provenance( + body.clone(), + rt.clone(), + item.params.clone(), + type_env.clone(), + acc.clone(), + ), + _ => v2_rt::rc_empty_map::< + String, + Rc< + HashMap< + String, + Rc< + HashMap< + String, + Rc, + >, + >, + >, + >, + >( + ), + }; + let has_scalar = + ((provenance.clone().len() as i64) > 0); + let has_variant = + ((Rc::new(v2_rt::map_keys(&variant_prov)).len() + as i64) + > 0); + if (has_scalar.clone() || has_variant.clone()) { + match v2_rt::map_get(&acc, fn_name.clone()) { + Some(sig) => v2_rt::rc_map_insert( + acc.clone(), + fn_name.clone(), + Rc::new(ResolvedFuncSig { + name: sig.name.clone(), + params: sig.params.clone(), + inferred: sig.inferred.clone(), + is_async: sig.is_async.clone(), + output_provenance: if has_scalar.clone() + { + provenance.clone() + } else { + sig.output_provenance.clone() + }, + variant_provenance: if has_variant + .clone() + { + variant_prov.clone() + } else { + sig.variant_provenance.clone() + }, + }), + ), + None => acc.clone(), + } + } else { + acc.clone() + } + } + } else { + acc.clone() + } + } + None => acc.clone(), + } } } + } else { + acc.clone() } - } - _ => acc.clone(), - } - }) + }, + ); + Rc::new(ResolvedFuncEnv { + signatures: updated_sigs, + }) + } } -pub fn merge_field_prov_maps( - a: Rc>>>>, - b: Rc>>>>, -) -> Rc>>>> { +pub fn annotate_descent_evidence( + body: Rc, + fn_name: String, + params: Rc>>, + type_env: Rc, + scope_locals: Rc>>, + func_sigs: Rc>>, +) -> Rc { { - let from_a = Rc::new(v2_rt::map_keys(&a)).iter().cloned().fold( - v2_rt::rc_empty_map::>>>(), - |result: Rc>>>>, - fname: String| match v2_rt::map_get(&a, fname.clone()) { - Some(a_prov) => match v2_rt::map_get(&b, fname.clone()) { - Some(b_prov) => v2_rt::rc_map_insert( - result.clone(), - fname.clone(), - union_prov_maps(a_prov.clone(), b_prov.clone()), - ), - None => v2_rt::rc_map_insert(result.clone(), fname.clone(), a_prov.clone()), - }, - None => result.clone(), + let param_name_map = params.clone().iter().cloned().fold( + v2_rt::rc_empty_map::(), + |acc: Rc>, p: Rc| { + let pname = param_node_name_at(p.clone(), type_env.source_indices.clone()); + let ptype = resolved_type_name(p.clone(), type_env.source_indices.clone()); + v2_rt::rc_map_insert(acc, pname.clone(), ptype.clone()) }, ); - Rc::new(v2_rt::map_keys(&b)).iter().cloned().fold( - from_a, - |result: Rc>>>>, - fname: String| { - if (v2_rt::map_get(&result, fname.clone()) != None) { - result.clone() - } else { - match v2_rt::map_get(&b, fname.clone()) { - Some(b_prov) => { - v2_rt::rc_map_insert(result.clone(), fname.clone(), b_prov.clone()) + let param_order_list = Rc::new({ + let mut __result = Vec::new(); + for p in params.clone().iter().cloned() { + __result.push(param_node_name_at( + p.clone(), + type_env.source_indices.clone(), + )); + } + __result + }); + let ctx = Rc::new(DescentContext { + fn_name: fn_name, + param_names: param_name_map, + param_order: param_order_list, + type_env: type_env.clone(), + sub_value_vars: v2_rt::rc_empty_map::>(), + size_aliases: v2_rt::rc_empty_map::>(), + scope_locals: scope_locals, + func_sigs: func_sigs, + per_field_vars: v2_rt::rc_empty_map::>>>( + ), + }); + annotate_descent(body, ctx) + } +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct InferPropertiesResult { + pub props: Rc>>, + pub diagnostics: Rc>>, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct InferTransportResult { + pub transport: Option>, + pub diagnostics: Rc>>, +} + +pub fn infer_property_values( + props: Rc>>, + scope: Rc, +) -> Rc { + { + let results = Rc::new({ + let mut __result = Vec::new(); + for p in props.iter().cloned() { + __result.push({ + let val = field_init_node_value(p.clone()); + let val_result = infer_expr(val.clone(), scope.clone(), None); + ( + Rc::new(Node { + name: p.name.clone(), + span: p.span.clone(), + ident_span: p.ident_span.clone(), + children: Rc::new(vec![val_result.typed.clone()]), + connective: p.connective.clone(), + params: p.params.clone(), + inferred: p.inferred.clone(), + return_cardinality: p.return_cardinality.clone(), + uses: p.uses.clone(), + body: p.body.clone(), + transport: p.transport.clone(), + properties: p.properties.clone(), + type_annotation: p.type_annotation.clone(), + is_self_recursive: p.is_self_recursive.clone(), + has_non_tail_self_call: p.has_non_tail_self_call.clone(), + match_pattern: p.match_pattern.clone(), + expr_data: p.expr_data.clone(), + ident: None, + binding_id: None, + }), + val_result.diagnostics.clone(), + ) + }); + } + __result + }); + Rc::new(InferPropertiesResult { + props: Rc::new({ + let mut __result = Vec::new(); + for r in results.clone().iter().cloned() { + __result.push(r.0.clone()); + } + __result + }), + diagnostics: Rc::new({ + let mut __result = Vec::new(); + for r in results.clone().iter().cloned() { + __result.extend((*r.1.clone()).iter().cloned()); + } + __result + }), + }) + } +} + +pub fn infer_auth_source_properties( + props: Rc>>, + scope: Rc, +) -> Rc { + { + let results = Rc::new({ + let mut __result = Vec::new(); + for p in props.iter().cloned() { + __result.push( + if (field_init_node_name_at( + p.clone(), + scope.type_env.clone().source_indices.clone(), + ) + .as_str() + == "svc_auth_source".to_string().as_str()) + { + { + let val = field_init_node_value(p.clone()); + let val_result = infer_expr(val.clone(), scope.clone(), None); + ( + Rc::new(Node { + name: p.name.clone(), + span: p.span.clone(), + ident_span: p.ident_span.clone(), + children: Rc::new(vec![val_result.typed.clone()]), + connective: p.connective.clone(), + params: p.params.clone(), + inferred: p.inferred.clone(), + return_cardinality: p.return_cardinality.clone(), + uses: p.uses.clone(), + body: p.body.clone(), + transport: p.transport.clone(), + properties: p.properties.clone(), + type_annotation: p.type_annotation.clone(), + is_self_recursive: p.is_self_recursive.clone(), + has_non_tail_self_call: p.has_non_tail_self_call.clone(), + match_pattern: p.match_pattern.clone(), + expr_data: p.expr_data.clone(), + ident: None, + binding_id: None, + }), + val_result.diagnostics.clone(), + ) } - None => result.clone(), - } + } else { + (p.clone(), Rc::new(vec![])) + }, + ); + } + __result + }); + Rc::new(InferPropertiesResult { + props: Rc::new({ + let mut __result = Vec::new(); + for r in results.clone().iter().cloned() { + __result.push(r.0.clone()); } - }, - ) + __result + }), + diagnostics: Rc::new({ + let mut __result = Vec::new(); + for r in results.clone().iter().cloned() { + __result.extend((*r.1.clone()).iter().cloned()); + } + __result + }), + }) } } -pub fn union_prov_maps( - a: Rc>>, - b: Rc>>, -) -> Rc>> { - { - let from_a = Rc::new(v2_rt::map_keys(&a)).iter().cloned().fold( - empty_prov_map(), - |result: Rc>>, key: String| match v2_rt::map_get( - &a, - key.clone(), - ) { - Some(a_rel) => match v2_rt::map_get(&b, key.clone()) { - Some(b_rel) => v2_rt::rc_map_insert( - result.clone(), - key.clone(), - join_sub_value(a_rel.clone(), b_rel.clone()), - ), - None => v2_rt::rc_map_insert(result.clone(), key.clone(), a_rel.clone()), - }, - None => result.clone(), - }, - ); - Rc::new(v2_rt::map_keys(&b)).iter().cloned().fold( - from_a, - |result: Rc>>, key: String| { - if (v2_rt::map_get(&result, key.clone()) != None) { - result.clone() +pub fn infer_transport_node( + transport: Option>, + scope: Rc, +) -> Rc { + match transport { + None => Rc::new(InferTransportResult { + transport: None, + diagnostics: Rc::new(vec![]), + }), + Some(t) => { + let prop_result = infer_property_values(t.properties.clone(), scope); + Rc::new(InferTransportResult { + transport: Some(Rc::new(Node { + name: t.name.clone(), + span: t.span.clone(), + ident_span: t.ident_span.clone(), + children: t.children.clone(), + connective: t.connective.clone(), + params: t.params.clone(), + inferred: t.inferred.clone(), + return_cardinality: t.return_cardinality.clone(), + uses: t.uses.clone(), + body: t.body.clone(), + transport: t.transport.clone(), + properties: prop_result.props.clone(), + type_annotation: t.type_annotation.clone(), + is_self_recursive: t.is_self_recursive.clone(), + has_non_tail_self_call: t.has_non_tail_self_call.clone(), + match_pattern: t.match_pattern.clone(), + expr_data: t.expr_data.clone(), + ident: None, + binding_id: None, + })), + diagnostics: prop_result.diagnostics.clone(), + }) + } + } +} + +pub fn infer_item(item: Rc, scope: Rc) -> Rc { + stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { + let typed_anno = item.type_annotation.clone(); + let transport_scope = if ((item.params.clone().len() as i64) > 0) { + build_params_scope(scope.clone(), item.params.clone()) + } else { + scope.clone() + }; + let transport_result = infer_transport_node(item.transport.clone(), transport_scope); + let typed_transport = transport_result.transport.clone(); + let transport_diags = transport_result.diagnostics.clone(); + let props_result = infer_auth_source_properties(item.properties.clone(), scope.clone()); + let typed_properties = props_result.props.clone(); + let props_diags = props_result.diagnostics.clone(); + if ((item.connective.clone() != Connective::NoConnective) + && (item.transport.clone() == None)) + { + Rc::new(TypedItemResult { + item: Rc::new(Node { + name: item.name.clone(), + span: item.span.clone(), + ident_span: item.ident_span.clone(), + children: Rc::new({ + let mut __result = Vec::new(); + for c in item.children.clone().iter().cloned() { + __result.push(infer_item(c.clone(), scope.clone()).item.clone()); + } + __result + }), + params: item.params.clone(), + inferred: Some(Rc::new(InferredNode::Resolved { node: unit_type() })), + return_cardinality: item.return_cardinality.clone(), + uses: item.uses.clone(), + body: None, + connective: item.connective.clone(), + transport: typed_transport, + properties: typed_properties, + type_annotation: typed_anno, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }), + diagnostics: v2_rt::concat(transport_diags, props_diags), + }) + } else { + if ((item.body.clone() != None) && ((item.params.clone().len() as i64) > 0)) { + { + let fn_scope = build_params_scope(scope.clone(), item.params.clone()); + let fn_scope = item.uses.clone().iter().cloned().fold( + fn_scope.clone(), + |s: Rc, u: Rc| { + extend_scope( + s, + resource_use_name_at( + u.clone(), + scope.type_env.clone().source_indices.clone(), + ), + resource_use_resource(u.clone()), + Rc::new(SubValueRelation::SubValueUnknown), + ) + }, + ); + let fn_return_expected = if (item.inferred.clone() != None) { + Some(resolved_type(item.clone())) + } else { + None + }; + let body_result = infer_expr( + item.body.clone().clone().unwrap(), + fn_scope.clone(), + fn_return_expected, + ); + let body_typed = body_result.typed.clone(); + let body_diags = body_result.diagnostics.clone(); + let inferred_ret = if (item.inferred.clone() != None) { + item.inferred.clone() + } else { + body_typed.inferred.clone() + }; + let is_recursive = expr_has_self_call( + body_typed.clone(), + authored_name_at( + scope.type_env.clone().source_indices.clone(), + item.clone(), + ), + scope.type_env.clone().source_indices.clone(), + ); + let annotated_body = if is_recursive.clone() { + annotate_descent_evidence( + body_typed.clone(), + authored_name_at( + scope.type_env.clone().source_indices.clone(), + item.clone(), + ), + item.params.clone(), + scope.type_env.clone(), + fn_scope.locals.clone(), + scope.func_env.clone().signatures.clone(), + ) + } else { + body_typed.clone() + }; + Rc::new(TypedItemResult { + item: Rc::new(Node { + name: item.name.clone(), + span: item.span.clone(), + ident_span: item.ident_span.clone(), + children: Rc::new({ + let mut __result = Vec::new(); + for c in item.children.clone().iter().cloned() { + __result + .push(infer_item(c.clone(), scope.clone()).item.clone()); + } + __result + }), + params: item.params.clone(), + inferred: inferred_ret, + return_cardinality: item.return_cardinality.clone(), + uses: item.uses.clone(), + body: Some(annotated_body), + connective: Connective::NoConnective, + transport: typed_transport, + properties: typed_properties, + type_annotation: typed_anno, + is_self_recursive: is_recursive.clone(), + has_non_tail_self_call: expr_has_non_tail_self_call( + body_typed.clone(), + authored_name_at( + scope.type_env.clone().source_indices.clone(), + item.clone(), + ), + true, + scope.type_env.clone().source_indices.clone(), + ), + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }), + diagnostics: v2_rt::concat( + v2_rt::concat(transport_diags, props_diags), + body_diags, + ), + }) + } + } else { + if (((item.body.clone() != None) && ((item.params.clone().len() as i64) == 0)) + && (item.inferred.clone() != None)) + { + { + let fn_scope = scope.clone(); + let body_result = infer_expr( + item.body.clone().clone().unwrap(), + fn_scope.clone(), + Some(resolved_type(item.clone())), + ); + let body_typed = body_result.typed.clone(); + let body_diags = body_result.diagnostics.clone(); + Rc::new(TypedItemResult { + item: Rc::new(Node { + name: item.name.clone(), + span: item.span.clone(), + ident_span: item.ident_span.clone(), + children: Rc::new(vec![]), + params: Rc::new(vec![]), + inferred: item.inferred.clone(), + return_cardinality: item.return_cardinality.clone(), + uses: Rc::new(vec![]), + body: Some(body_typed.clone()), + connective: Connective::NoConnective, + transport: typed_transport, + properties: typed_properties, + type_annotation: typed_anno, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }), + diagnostics: v2_rt::concat( + v2_rt::concat(transport_diags, props_diags), + body_diags, + ), + }) + } } else { - match v2_rt::map_get(&b, key.clone()) { - Some(b_rel) => { - v2_rt::rc_map_insert(result.clone(), key.clone(), b_rel.clone()) + if ((item.body.clone() != None) && ((item.params.clone().len() as i64) == 0)) { + { + let data_expected = if (item.type_annotation.clone() != None) { + Some(item.type_annotation.clone().clone().unwrap()) + } else { + None + }; + let val_result = infer_expr( + item.body.clone().clone().unwrap(), + scope.clone(), + data_expected, + ); + let val_typed = val_result.typed.clone(); + let val_diags = val_result.diagnostics.clone(); + let inferred_ret = if (item.type_annotation.clone() != None) { + Some(Rc::new(InferredNode::Resolved { + node: item.type_annotation.clone().clone().unwrap(), + })) + } else { + val_typed.inferred.clone() + }; + Rc::new(TypedItemResult { + item: Rc::new(Node { + name: item.name.clone(), + span: item.span.clone(), + ident_span: item.ident_span.clone(), + children: Rc::new(vec![]), + params: Rc::new(vec![]), + inferred: inferred_ret, + return_cardinality: item.return_cardinality.clone(), + uses: Rc::new(vec![]), + body: Some(val_typed.clone()), + connective: Connective::NoConnective, + transport: typed_transport, + properties: typed_properties, + type_annotation: typed_anno, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }), + diagnostics: v2_rt::concat( + v2_rt::concat(transport_diags, props_diags), + val_diags, + ), + }) } - None => result.clone(), - } - } - }, - ) - } -} - -pub fn populate_output_provenance( - typed_items: Rc>>, - func_env: Rc, - type_env: Rc, - locals: Rc>>, -) -> Rc { - { - let updated_sigs = typed_items.iter().cloned().fold( - func_env.signatures.clone(), - |acc: Rc>>, item: Rc| { - if ((item.params.clone().len() as i64) > 0) { - { - let fn_name = - authored_name_at(type_env.source_indices.clone(), item.clone()); - if (is_child_accessor_in_model(fn_name.clone()) - || is_tree_size_reducing(fn_name.clone())) + } else { + if (((item.params.clone().len() as i64) > 0) && (item.body.clone() == None)) { - match item.params.clone().first().cloned() { - Some(first_param) => { - let pname = param_node_name_at( - first_param.clone(), - type_env.source_indices.clone(), - ); - let ptype = resolved_type_name( - first_param.clone(), - type_env.source_indices.clone(), - ); - if ((ptype.clone().as_str() != "".to_string().as_str()) - && (pname.clone().as_str() != "".to_string().as_str())) - { - { - let fields = inductive_fields_for( - type_env.clone(), - ptype.clone(), - ); - let list_field = Rc::new({ - let mut __result = Vec::new(); - for f in fields.clone().iter().cloned() { - if match f.shape.clone() { - RecursionShape::ListRecursion => true, - _ => false, - } { - __result.push(f); - } - } - __result - }) - .first() - .cloned(); - match list_field.clone() { - Some(ind_field) => { - let relation = - Rc::new(SubValueRelation::StrictSubValue { - field: ind_field.clone(), - factor: Rc::new( - ShrinkFactor::UnitShrink, - ), - }); - let provenance = - Rc::new(vec![v2_rt::rc_map_insert( - v2_rt::rc_empty_map::< - String, - Rc, - >( - ), - pname.clone(), - relation.clone(), - )]); - match v2_rt::map_get(&acc, fn_name.clone()) { - Some(sig) => v2_rt::rc_map_insert( - acc.clone(), - fn_name.clone(), - Rc::new(ResolvedFuncSig { - name: sig.name.clone(), - params: sig.params.clone(), - inferred: sig.inferred.clone(), - is_async: sig.is_async.clone(), - output_provenance: provenance - .clone(), - variant_provenance: sig - .variant_provenance - .clone(), - }), - ), - None => acc.clone(), - } - } - None => acc.clone(), - } - } - } else { - acc.clone() - } - } - None => acc.clone(), - } - } else { - match item.body.clone() { - Some(body) => { - if !expr_has_self_call( - body.clone(), - fn_name.clone(), - type_env.source_indices.clone(), - ) { - { - let provenance = infer_output_provenance( - body.clone(), - item.params.clone(), - type_env.clone(), - locals.clone(), - acc.clone(), - ); - let variant_prov = - match item.inferred.clone().as_deref().cloned() { - Some(InferredNode::Resolved { - node: rt, - .. - }) => compute_variant_provenance( - body.clone(), - rt.clone(), - item.params.clone(), - type_env.clone(), - acc.clone(), - ), - _ => v2_rt::rc_empty_map::< - String, - Rc< - HashMap< - String, - Rc< - HashMap< - String, - Rc, - >, - >, - >, - >, - >( - ), - }; - let has_scalar = - ((provenance.clone().len() as i64) > 0); - let has_variant = - ((Rc::new(v2_rt::map_keys(&variant_prov)).len() - as i64) - > 0); - if (has_scalar.clone() || has_variant.clone()) { - match v2_rt::map_get(&acc, fn_name.clone()) { - Some(sig) => v2_rt::rc_map_insert( - acc.clone(), - fn_name.clone(), - Rc::new(ResolvedFuncSig { - name: sig.name.clone(), - params: sig.params.clone(), - inferred: sig.inferred.clone(), - is_async: sig.is_async.clone(), - output_provenance: if has_scalar.clone() - { - provenance.clone() - } else { - sig.output_provenance.clone() - }, - variant_provenance: if has_variant - .clone() - { - variant_prov.clone() - } else { - sig.variant_provenance.clone() - }, - }), - ), - None => acc.clone(), - } - } else { - acc.clone() - } + Rc::new(TypedItemResult { + item: Rc::new(Node { + name: item.name.clone(), + span: item.span.clone(), + ident_span: item.ident_span.clone(), + children: Rc::new({ + let mut __result = Vec::new(); + for c in item.children.clone().iter().cloned() { + __result.push( + infer_item(c.clone(), scope.clone()).item.clone(), + ); } + __result + }), + params: item.params.clone(), + inferred: if (item.inferred.clone() != None) { + item.inferred.clone() } else { - acc.clone() - } - } - None => acc.clone(), - } + Some(Rc::new(InferredNode::Resolved { node: unit_type() })) + }, + return_cardinality: item.return_cardinality.clone(), + uses: item.uses.clone(), + body: None, + connective: Connective::NoConnective, + transport: typed_transport, + properties: typed_properties, + type_annotation: typed_anno, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }), + diagnostics: v2_rt::concat(transport_diags, props_diags), + }) + } else { + Rc::new(TypedItemResult { + item: Rc::new(Node { + name: item.name.clone(), + span: item.span.clone(), + ident_span: item.ident_span.clone(), + children: Rc::new({ + let mut __result = Vec::new(); + for c in item.children.clone().iter().cloned() { + __result.push( + infer_item(c.clone(), scope.clone()).item.clone(), + ); + } + __result + }), + params: item.params.clone(), + inferred: if (item.inferred.clone() != None) { + item.inferred.clone() + } else { + Some(Rc::new(InferredNode::Resolved { node: unit_type() })) + }, + return_cardinality: item.return_cardinality.clone(), + uses: item.uses.clone(), + body: None, + connective: item.connective.clone(), + transport: typed_transport, + properties: typed_properties, + type_annotation: typed_anno, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }), + diagnostics: v2_rt::concat(transport_diags, props_diags), + }) } } - } else { - acc.clone() } - }, - ); - Rc::new(ResolvedFuncEnv { - signatures: updated_sigs, - }) + } + } + }) +} + +pub fn infer_items( + items: Rc>>, + scope: Rc, +) -> Rc>> { + Rc::new({ + let mut __result = Vec::new(); + for item in items.iter().cloned() { + __result.push(infer_item(item.clone(), scope.clone())); + } + __result + }) +} + +pub fn is_type_variable_name(name: String) -> bool { + (((((name.clone().as_str() == "T".to_string().as_str()) + || (name.clone().as_str() == "K".to_string().as_str())) + || (name.clone().as_str() == "V".to_string().as_str())) + || (name.clone().as_str() == "MappedElement".to_string().as_str())) + || (name.clone().as_str() == "FoldAccumulator".to_string().as_str())) +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct ArgGenericFoldState { + pub results: Rc>>, + pub subst: Rc>>, +} + +pub fn param_is_generic_decl( + p: Rc, + source_indices: Rc>>, +) -> bool { + { + let pt = param_node_type_expr(p.clone()); + let pname = param_node_name_at(p.clone(), source_indices.clone()); + let tname = authored_name_at(source_indices.clone(), pt.clone()); + ((((pt.children.clone().len() as i64) == 0) + && (pt.connective.clone() == Connective::NoConnective)) + && ((pname.clone().as_str() != "".to_string().as_str()) + && (pname.clone().as_str() == tname.as_str()))) } } -pub fn annotate_descent_evidence( - body: Rc, - fn_name: String, - params: Rc>>, - type_env: Rc, - scope_locals: Rc>>, - func_sigs: Rc>>, +pub fn unify_generics( + mut formal: Rc, + mut actual: Rc, + mut generic_names: Rc>, + mut source_indices: Rc>>, + mut acc: Rc>>, +) -> Rc>> { + loop { + let fname = authored_name_at(source_indices.clone(), formal.clone()); + let f_bare = (((formal.children.clone().len() as i64) == 0) + && (formal.connective.clone() == Connective::NoConnective)); + if (f_bare && { + let mut __found = false; + for g in generic_names.clone().iter().cloned() { + if (g.clone().as_str() == fname.clone().as_str()) { + __found = true; + break; + } + } + __found + }) { + match v2_rt::map_get(&acc, fname.clone()) { + None => { + break v2_rt::rc_map_insert(acc.clone(), fname.clone(), actual.clone()); + } + Some(_) => { + break acc.clone(); + } + } + } else { + if (((formal.children.clone().len() as i64) == 1) + && ((actual.children.clone().len() as i64) == 1)) + { + match formal.children.clone().first().cloned() { + Some(fc) => match actual.children.clone().first().cloned() { + Some(ac) => { + let __tco_0 = fc.clone(); + let __tco_1 = ac.clone(); + formal = __tco_0; + actual = __tco_1; + continue; + } + None => { + break acc.clone(); + } + }, + None => { + break acc.clone(); + } + } + } else { + break acc.clone(); + } + } + } +} + +pub fn substitute_generics( + n: Rc, + subst: Rc>>, + source_indices: Rc>>, ) -> Rc { - { - let param_name_map = params.clone().iter().cloned().fold( - v2_rt::rc_empty_map::(), - |acc: Rc>, p: Rc| { - let pname = param_node_name_at(p.clone(), type_env.source_indices.clone()); - let ptype = resolved_type_name(p.clone(), type_env.source_indices.clone()); - v2_rt::rc_map_insert(acc, pname.clone(), ptype.clone()) - }, - ); - let param_order_list = Rc::new({ - let mut __result = Vec::new(); - for p in params.clone().iter().cloned() { - __result.push(param_node_name_at( - p.clone(), - type_env.source_indices.clone(), - )); + stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { + if ((Rc::new(v2_rt::map_keys(&subst)).len() as i64) == 0) { + n.clone() + } else { + { + let nm = authored_name_at(source_indices.clone(), n.clone()); + let is_bare = ((((n.children.clone().len() as i64) == 0) + && (n.connective.clone() == Connective::NoConnective)) + && ((n.params.clone().len() as i64) == 0)); + if is_bare { + match v2_rt::map_get(&subst, nm) { + Some(c) => c.clone(), + None => n.clone(), + } + } else { + Rc::new(Node { + name: n.name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), + span: n.span.clone(), + ident_span: n.ident_span.clone(), + children: Rc::new({ + let mut __result = Vec::new(); + for c in n.children.clone().iter().cloned() { + __result.push(substitute_generics( + c.clone(), + subst.clone(), + source_indices.clone(), + )); + } + __result + }), + connective: n.connective.clone(), + params: Rc::new({ + let mut __result = Vec::new(); + for p in n.params.clone().iter().cloned() { + __result.push(substitute_generics( + p.clone(), + subst.clone(), + source_indices.clone(), + )); + } + __result + }), + inferred: match n.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: rt, .. }) => { + Some(Rc::new(InferredNode::Resolved { + node: substitute_generics( + rt.clone(), + subst.clone(), + source_indices.clone(), + ), + })) + } + _ => n.inferred.clone(), + }, + return_cardinality: n.return_cardinality.clone(), + uses: n.uses.clone(), + body: n.body.clone(), + transport: n.transport.clone(), + properties: n.properties.clone(), + type_annotation: n.type_annotation.clone(), + is_self_recursive: n.is_self_recursive.clone(), + has_non_tail_self_call: n.has_non_tail_self_call.clone(), + match_pattern: n.match_pattern.clone(), + expr_data: n.expr_data.clone(), + }) + } } - __result - }); - let ctx = Rc::new(DescentContext { - fn_name: fn_name, - param_names: param_name_map, - param_order: param_order_list, - type_env: type_env.clone(), - sub_value_vars: v2_rt::rc_empty_map::>(), - size_aliases: v2_rt::rc_empty_map::>(), - scope_locals: scope_locals, - func_sigs: func_sigs, - per_field_vars: v2_rt::rc_empty_map::>>>( - ), - }); - annotate_descent(body, ctx) - } + } + }) } -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct InferPropertiesResult { - pub props: Rc>>, - pub diagnostics: Rc>>, +pub fn collect_parent_bindings_filtered( + envs: Rc>>, +) -> Rc>> { + envs.iter().cloned().fold( + v2_rt::rc_empty_map::>(), + |acc: Rc>>, env: Rc| { + Rc::new(v2_rt::map_keys(&env.bindings.clone())) + .iter() + .cloned() + .fold( + acc, + |bacc: Rc>>, ident: i64| { + let name = intern_str(env.intern_table.clone(), ident.clone()); + if is_type_variable_name(name.clone()) { + bacc.clone() + } else { + match v2_rt::map_get(&env.bindings.clone(), ident.clone()) { + Some(binding) => v2_rt::rc_map_insert( + bacc.clone(), + ident.clone(), + binding.clone(), + ), + None => bacc.clone(), + } + } + }, + ) + }, + ) } -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct InferTransportResult { - pub transport: Option>, - pub diagnostics: Rc>>, +pub fn collect_parent_carrier_bindings( + envs: Rc>>, +) -> Rc>> { + envs.iter().cloned().fold( + v2_rt::rc_empty_map::>(), + |acc: Rc>>, env: Rc| { + let with_existing = v2_rt::rc_map_merge(acc, env.carrier_bindings.clone()); + Rc::new(v2_rt::map_values(&env.bindings.clone())) + .iter() + .cloned() + .fold( + with_existing.clone(), + |bacc: Rc>>, binding: Rc| { + match binding.resolved.clone().binding_id.clone() { + Some(binding_id) => v2_rt::rc_map_insert( + bacc.clone(), + binding_id.clone(), + binding.clone(), + ), + None => bacc.clone(), + } + }, + ) + }, + ) } -pub fn infer_property_values( - props: Rc>>, - scope: Rc, -) -> Rc { - { - let results = Rc::new({ - let mut __result = Vec::new(); - for p in props.iter().cloned() { - __result.push({ - let val = field_init_node_value(p.clone()); - let val_result = infer_expr(val.clone(), scope.clone(), None); - ( - Rc::new(Node { - name: p.name.clone(), - span: p.span.clone(), - ident_span: p.ident_span.clone(), - children: Rc::new(vec![val_result.typed.clone()]), - connective: p.connective.clone(), - params: p.params.clone(), - inferred: p.inferred.clone(), - return_cardinality: p.return_cardinality.clone(), - uses: p.uses.clone(), - body: p.body.clone(), - transport: p.transport.clone(), - properties: p.properties.clone(), - type_annotation: p.type_annotation.clone(), - is_self_recursive: p.is_self_recursive.clone(), - has_non_tail_self_call: p.has_non_tail_self_call.clone(), - match_pattern: p.match_pattern.clone(), - expr_data: p.expr_data.clone(), - ident: None, - }), - val_result.diagnostics.clone(), - ) - }); +pub fn lookup_type_binding_by_name_in_env( + env: Rc, + name: String, +) -> Option> { + match Rc::new({ + let mut __result = Vec::new(); + for binding in Rc::new(v2_rt::map_values(&env.bindings.clone())) + .iter() + .cloned() + { + if (binding.name.clone().as_str() == name.clone().as_str()) { + __result.push(binding); } - __result - }); - Rc::new(InferPropertiesResult { - props: Rc::new({ - let mut __result = Vec::new(); - for r in results.clone().iter().cloned() { - __result.push(r.0.clone()); - } - __result - }), - diagnostics: Rc::new({ - let mut __result = Vec::new(); - for r in results.clone().iter().cloned() { - __result.extend((*r.1.clone()).iter().cloned()); - } - __result - }), - }) - } -} - -pub fn infer_auth_source_properties( - props: Rc>>, - scope: Rc, -) -> Rc { + } + __result + }) + .first() + .cloned() { - let results = Rc::new({ + Some(binding) => Some(binding.clone()), + None => match Rc::new({ let mut __result = Vec::new(); - for p in props.iter().cloned() { - __result.push( - if (field_init_node_name_at( - p.clone(), - scope.type_env.clone().source_indices.clone(), - ) - .as_str() - == "svc_auth_source".to_string().as_str()) - { - { - let val = field_init_node_value(p.clone()); - let val_result = infer_expr(val.clone(), scope.clone(), None); - ( - Rc::new(Node { - name: p.name.clone(), - span: p.span.clone(), - ident_span: p.ident_span.clone(), - children: Rc::new(vec![val_result.typed.clone()]), - connective: p.connective.clone(), - params: p.params.clone(), - inferred: p.inferred.clone(), - return_cardinality: p.return_cardinality.clone(), - uses: p.uses.clone(), - body: p.body.clone(), - transport: p.transport.clone(), - properties: p.properties.clone(), - type_annotation: p.type_annotation.clone(), - is_self_recursive: p.is_self_recursive.clone(), - has_non_tail_self_call: p.has_non_tail_self_call.clone(), - match_pattern: p.match_pattern.clone(), - expr_data: p.expr_data.clone(), - ident: None, - }), - val_result.diagnostics.clone(), - ) - } - } else { - (p.clone(), Rc::new(vec![])) - }, - ); - } - __result - }); - Rc::new(InferPropertiesResult { - props: Rc::new({ - let mut __result = Vec::new(); - for r in results.clone().iter().cloned() { - __result.push(r.0.clone()); - } - __result - }), - diagnostics: Rc::new({ - let mut __result = Vec::new(); - for r in results.clone().iter().cloned() { - __result.extend((*r.1.clone()).iter().cloned()); + for binding in Rc::new(v2_rt::map_values(&env.carrier_bindings.clone())) + .iter() + .cloned() + { + if (binding.name.clone().as_str() == name.clone().as_str()) { + __result.push(binding); } - __result - }), - }) - } -} - -pub fn infer_transport_node( - transport: Option>, - scope: Rc, -) -> Rc { - match transport { - None => Rc::new(InferTransportResult { - transport: None, - diagnostics: Rc::new(vec![]), - }), - Some(t) => { - let prop_result = infer_property_values(t.properties.clone(), scope); - Rc::new(InferTransportResult { - transport: Some(Rc::new(Node { - name: t.name.clone(), - span: t.span.clone(), - ident_span: t.ident_span.clone(), - children: t.children.clone(), - connective: t.connective.clone(), - params: t.params.clone(), - inferred: t.inferred.clone(), - return_cardinality: t.return_cardinality.clone(), - uses: t.uses.clone(), - body: t.body.clone(), - transport: t.transport.clone(), - properties: prop_result.props.clone(), - type_annotation: t.type_annotation.clone(), - is_self_recursive: t.is_self_recursive.clone(), - has_non_tail_self_call: t.has_non_tail_self_call.clone(), - match_pattern: t.match_pattern.clone(), - expr_data: t.expr_data.clone(), - ident: None, - })), - diagnostics: prop_result.diagnostics.clone(), - }) + } + __result + }) + .first() + .cloned() + { + Some(binding) => Some(binding.clone()), + None => None, + }, + } +} + +pub fn lookup_coproduct_parent_binding_by_variant( + env: Rc, + variant_name: String, +) -> Option> { + { + let visible_matches = Rc::new({ + let mut __result = Vec::new(); + for binding in Rc::new(v2_rt::map_values(&env.bindings.clone())) + .iter() + .cloned() + { + if ((binding.resolved.clone().connective.clone() == Connective::Disj) + && has_child_named( + binding.resolved.clone(), + variant_name.clone(), + env.source_indices.clone(), + )) + { + __result.push(binding); + } + } + __result + }); + let carrier_matches = Rc::new({ + let mut __result = Vec::new(); + for binding in Rc::new(v2_rt::map_values(&env.carrier_bindings.clone())) + .iter() + .cloned() + { + if ((binding.resolved.clone().connective.clone() == Connective::Disj) + && has_child_named( + binding.resolved.clone(), + variant_name.clone(), + env.source_indices.clone(), + )) + { + __result.push(binding); + } + } + __result + }); + let matches = v2_rt::concat(visible_matches, carrier_matches); + if ((matches.clone().len() as i64) == 1) { + matches.clone().first().cloned() + } else { + None } } } -pub fn infer_item(item: Rc, scope: Rc) -> Rc { +pub fn stamp_hidden_dependency_refs( + n: Rc, + dep_env: Rc, + source_indices: Rc>>, +) -> Rc { stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { - let typed_anno = item.type_annotation.clone(); - let transport_scope = if ((item.params.clone().len() as i64) > 0) { - build_params_scope(scope.clone(), item.params.clone()) - } else { - scope.clone() + let stamped_children = Rc::new({ + let mut __result = Vec::new(); + for child in n.children.clone().iter().cloned() { + __result.push(stamp_hidden_dependency_refs( + child.clone(), + dep_env.clone(), + source_indices.clone(), + )); + } + __result + }); + let stamped_params = Rc::new({ + let mut __result = Vec::new(); + for param in n.params.clone().iter().cloned() { + __result.push(stamp_hidden_dependency_refs( + param.clone(), + dep_env.clone(), + source_indices.clone(), + )); + } + __result + }); + let stamped_inferred = match n.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: rt, .. }) => { + Some(Rc::new(InferredNode::Resolved { + node: stamp_hidden_dependency_refs( + rt.clone(), + dep_env.clone(), + source_indices.clone(), + ), + })) + } + _ => n.inferred.clone(), }; - let transport_result = infer_transport_node(item.transport.clone(), transport_scope); - let typed_transport = transport_result.transport.clone(); - let transport_diags = transport_result.diagnostics.clone(); - let props_result = infer_auth_source_properties(item.properties.clone(), scope.clone()); - let typed_properties = props_result.props.clone(); - let props_diags = props_result.diagnostics.clone(); - if ((item.connective.clone() != Connective::NoConnective) - && (item.transport.clone() == None)) - { - Rc::new(TypedItemResult { - item: Rc::new(Node { - name: item.name.clone(), - span: item.span.clone(), - ident_span: item.ident_span.clone(), - children: Rc::new({ - let mut __result = Vec::new(); - for c in item.children.clone().iter().cloned() { - __result.push(infer_item(c.clone(), scope.clone()).item.clone()); - } - __result - }), - params: item.params.clone(), - inferred: Some(Rc::new(InferredNode::Resolved { node: unit_type() })), - return_cardinality: item.return_cardinality.clone(), - uses: item.uses.clone(), - body: None, - connective: item.connective.clone(), - transport: typed_transport, - properties: typed_properties, - type_annotation: typed_anno, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }), - diagnostics: v2_rt::concat(transport_diags, props_diags), - }) - } else { - if ((item.body.clone() != None) && ((item.params.clone().len() as i64) > 0)) { - { - let fn_scope = build_params_scope(scope.clone(), item.params.clone()); - let fn_scope = item.uses.clone().iter().cloned().fold( - fn_scope.clone(), - |s: Rc, u: Rc| { - extend_scope( - s, - resource_use_name_at( - u.clone(), - scope.type_env.clone().source_indices.clone(), - ), - resource_use_resource(u.clone()), - Rc::new(SubValueRelation::SubValueUnknown), - ) - }, - ); - let fn_return_expected = if (item.inferred.clone() != None) { - Some(resolved_type(item.clone())) - } else { - None - }; - let body_result = infer_expr( - item.body.clone().clone().unwrap(), - fn_scope.clone(), - fn_return_expected, - ); - let body_typed = body_result.typed.clone(); - let body_diags = body_result.diagnostics.clone(); - let inferred_ret = if (item.inferred.clone() != None) { - item.inferred.clone() - } else { - body_typed.inferred.clone() - }; - let is_recursive = expr_has_self_call( - body_typed.clone(), - authored_name_at( - scope.type_env.clone().source_indices.clone(), - item.clone(), - ), - scope.type_env.clone().source_indices.clone(), - ); - let annotated_body = if is_recursive.clone() { - annotate_descent_evidence( - body_typed.clone(), - authored_name_at( - scope.type_env.clone().source_indices.clone(), - item.clone(), - ), - item.params.clone(), - scope.type_env.clone(), - fn_scope.locals.clone(), - scope.func_env.clone().signatures.clone(), - ) + let rebuilt = Rc::new(Node { + name: n.name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), + span: n.span.clone(), + ident_span: n.ident_span.clone(), + children: stamped_children, + connective: n.connective.clone(), + params: stamped_params, + inferred: stamped_inferred, + return_cardinality: n.return_cardinality.clone(), + uses: n.uses.clone(), + body: n.body.clone(), + transport: n.transport.clone(), + properties: n.properties.clone(), + type_annotation: n.type_annotation.clone(), + is_self_recursive: n.is_self_recursive.clone(), + has_non_tail_self_call: n.has_non_tail_self_call.clone(), + match_pattern: n.match_pattern.clone(), + expr_data: n.expr_data.clone(), + }); + let name = authored_name_at(source_indices.clone(), rebuilt.clone()); + let bare_unbranded_ref = (((((rebuilt.binding_id.clone() == None) + && (rebuilt.connective.clone() == Connective::NoConnective)) + && ((rebuilt.children.clone().len() as i64) == 0)) + && ((rebuilt.params.clone().len() as i64) == 0)) + && (name.clone().as_str() != "".to_string().as_str())); + if bare_unbranded_ref { + match lookup_type_binding_by_name_in_env(dep_env.clone(), name.clone()) { + Some(binding) => { + if (binding.resolved.clone().binding_id.clone() != None) { + node_with_preserved_binding_id(binding.resolved.clone(), rebuilt.clone()) } else { - body_typed.clone() - }; - Rc::new(TypedItemResult { - item: Rc::new(Node { - name: item.name.clone(), - span: item.span.clone(), - ident_span: item.ident_span.clone(), - children: Rc::new({ - let mut __result = Vec::new(); - for c in item.children.clone().iter().cloned() { - __result - .push(infer_item(c.clone(), scope.clone()).item.clone()); - } - __result - }), - params: item.params.clone(), - inferred: inferred_ret, - return_cardinality: item.return_cardinality.clone(), - uses: item.uses.clone(), - body: Some(annotated_body), - connective: Connective::NoConnective, - transport: typed_transport, - properties: typed_properties, - type_annotation: typed_anno, - is_self_recursive: is_recursive.clone(), - has_non_tail_self_call: expr_has_non_tail_self_call( - body_typed.clone(), - authored_name_at( - scope.type_env.clone().source_indices.clone(), - item.clone(), - ), - true, - scope.type_env.clone().source_indices.clone(), - ), - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }), - diagnostics: v2_rt::concat( - v2_rt::concat(transport_diags, props_diags), - body_diags, - ), - }) + rebuilt.clone() + } } - } else { - if (((item.body.clone() != None) && ((item.params.clone().len() as i64) == 0)) - && (item.inferred.clone() != None)) - { - { - let fn_scope = scope.clone(); - let body_result = infer_expr( - item.body.clone().clone().unwrap(), - fn_scope.clone(), - Some(resolved_type(item.clone())), - ); - let body_typed = body_result.typed.clone(); - let body_diags = body_result.diagnostics.clone(); - Rc::new(TypedItemResult { - item: Rc::new(Node { - name: item.name.clone(), - span: item.span.clone(), - ident_span: item.ident_span.clone(), - children: Rc::new(vec![]), - params: Rc::new(vec![]), - inferred: item.inferred.clone(), - return_cardinality: item.return_cardinality.clone(), - uses: Rc::new(vec![]), - body: Some(body_typed.clone()), - connective: Connective::NoConnective, - transport: typed_transport, - properties: typed_properties, - type_annotation: typed_anno, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }), - diagnostics: v2_rt::concat( - v2_rt::concat(transport_diags, props_diags), - body_diags, + None => rebuilt.clone(), + } + } else { + rebuilt.clone() + } + }) +} + +pub fn stamp_type_binding_dependency_refs( + binding: Rc, + dep_env: Rc, + source_indices: Rc>>, +) -> Rc { + Rc::new(TypeBinding { + name: binding.name.clone(), + resolved: stamp_hidden_dependency_refs(binding.resolved.clone(), dep_env, source_indices), + provenance: binding.provenance.clone(), + }) +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct CarrierClosureState { + pub carrier_bindings: Rc>>, + pub seen_names: Rc>, + pub seen_binding_ids: Rc>, +} + +pub fn lookup_decl_type_binding_by_name_excluding_binding_id( + env: Rc, + name: String, + excluded_binding_id: BindingId, +) -> Option> { + Rc::new(v2_rt::map_values(&env.decl_registry.clone())) + .iter() + .cloned() + .fold( + None, + |acc: Option>, decl: Rc| match acc.clone() { + Some(_) => acc.clone(), + None => { + if ((decl.name.clone().as_str() == name.clone().as_str()) + && (decl.binding_id.clone() != excluded_binding_id.clone())) + { + match v2_rt::map_get(&env.bindings.clone(), decl.binding_key.clone()) { + Some(binding) => { + if node_has_binding_id( + binding.resolved.clone(), + decl.binding_id.clone(), + ) { + Some(binding.clone()) + } else { + v2_rt::map_get( + &env.carrier_bindings.clone(), + decl.binding_id.clone(), + ) + } + } + None => v2_rt::map_get( + &env.carrier_bindings.clone(), + decl.binding_id.clone(), ), - }) + } + } else { + None } - } else { - if ((item.body.clone() != None) && ((item.params.clone().len() as i64) == 0)) { + } + }, + ) +} + +pub fn carrier_authority_target( + binding: Rc, + dep_env: Rc, + target_name: String, + fallback: Rc, +) -> Rc { + match binding.resolved.clone().binding_id.clone() { + Some(alias_binding_id) => match lookup_decl_type_binding_by_name_excluding_binding_id( + dep_env, + target_name, + alias_binding_id.clone(), + ) { + Some(target_binding) => target_binding.resolved.clone(), + None => fallback, + }, + None => fallback, + } +} + +pub fn carrier_authority_binding( + binding: Rc, + dep_env: Rc, + source_indices: Rc>>, +) -> Rc { + { + let resolved = binding.resolved.clone(); + if (((resolved.connective.clone() == Connective::NoConnective) + && ((resolved.children.clone().len() as i64) == 0)) + && ((resolved.params.clone().len() as i64) == 0)) + { + match resolved.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: target, .. }) => { + let declared_or_structural_target = ((target.binding_id.clone() != None) + || (target.connective.clone() != Connective::NoConnective)); + if declared_or_structural_target { { - let data_expected = if (item.type_annotation.clone() != None) { - Some(item.type_annotation.clone().clone().unwrap()) - } else { - None - }; - let val_result = infer_expr( - item.body.clone().clone().unwrap(), - scope.clone(), - data_expected, - ); - let val_typed = val_result.typed.clone(); - let val_diags = val_result.diagnostics.clone(); - let inferred_ret = if (item.type_annotation.clone() != None) { - Some(Rc::new(InferredNode::Resolved { - node: item.type_annotation.clone().clone().unwrap(), - })) - } else { - val_typed.inferred.clone() - }; - Rc::new(TypedItemResult { - item: Rc::new(Node { - name: item.name.clone(), - span: item.span.clone(), - ident_span: item.ident_span.clone(), - children: Rc::new(vec![]), - params: Rc::new(vec![]), - inferred: inferred_ret, - return_cardinality: item.return_cardinality.clone(), - uses: Rc::new(vec![]), - body: Some(val_typed.clone()), - connective: Connective::NoConnective, - transport: typed_transport, - properties: typed_properties, - type_annotation: typed_anno, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }), - diagnostics: v2_rt::concat( - v2_rt::concat(transport_diags, props_diags), - val_diags, + let target_name = authored_name_at(source_indices, target.clone()); + let target_authority = + match lookup_type_by_name(dep_env.clone(), target_name.clone()) { + Some(resolved_target) => resolved_target.clone(), + None => target.clone(), + }; + Rc::new(TypeBinding { + name: binding.name.clone(), + resolved: carrier_authority_target( + binding.clone(), + dep_env.clone(), + target_name.clone(), + target_authority, ), + provenance: binding.provenance.clone(), }) } } else { - if (((item.params.clone().len() as i64) > 0) && (item.body.clone() == None)) - { - Rc::new(TypedItemResult { - item: Rc::new(Node { - name: item.name.clone(), - span: item.span.clone(), - ident_span: item.ident_span.clone(), - children: Rc::new({ - let mut __result = Vec::new(); - for c in item.children.clone().iter().cloned() { - __result.push( - infer_item(c.clone(), scope.clone()).item.clone(), - ); - } - __result - }), - params: item.params.clone(), - inferred: if (item.inferred.clone() != None) { - item.inferred.clone() - } else { - Some(Rc::new(InferredNode::Resolved { node: unit_type() })) - }, - return_cardinality: item.return_cardinality.clone(), - uses: item.uses.clone(), - body: None, - connective: Connective::NoConnective, - transport: typed_transport, - properties: typed_properties, - type_annotation: typed_anno, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }), - diagnostics: v2_rt::concat(transport_diags, props_diags), - }) + binding.clone() + } + } + _ => binding.clone(), + } + } else { + { + let carrier_is_structural_shell = (((resolved.connective.clone() + != Connective::NoConnective) + || ((resolved.children.clone().len() as i64) > 0)) + || ((resolved.params.clone().len() as i64) > 0)); + let carrier_name = authored_name_at(source_indices, resolved.clone()); + if ((carrier_is_structural_shell + && (carrier_name.clone().as_str() != "".to_string().as_str())) + && (binding.name.clone().as_str() != carrier_name.clone().as_str())) + { + Rc::new(TypeBinding { + name: binding.name.clone(), + resolved: carrier_authority_target( + binding.clone(), + dep_env.clone(), + carrier_name.clone(), + resolved.clone(), + ), + provenance: binding.provenance.clone(), + }) + } else { + binding.clone() + } + } + } + } +} + +pub fn type_binding_decl_binding_id( + env: Rc, + binding: Rc, +) -> Option { + match binding.resolved.clone().binding_id.clone() { + Some(binding_id) => match v2_rt::map_get(&env.decl_registry.clone(), binding_id.clone()) { + Some(decl) => { + if decl.name.clone().as_str() == binding.name.clone().as_str() { + Some(binding_id.clone()) + } else { + None + } + } + None => None, + }, + None => Rc::new(v2_rt::map_values(&env.decl_registry.clone())) + .iter() + .cloned() + .fold( + None, + |acc: Option, decl: Rc| match acc.clone() { + Some(_) => acc.clone(), + None => { + if decl.name.clone().as_str() == binding.name.clone().as_str() { + Some(decl.binding_id.clone()) } else { - Rc::new(TypedItemResult { - item: Rc::new(Node { - name: item.name.clone(), - span: item.span.clone(), - ident_span: item.ident_span.clone(), - children: Rc::new({ - let mut __result = Vec::new(); - for c in item.children.clone().iter().cloned() { - __result.push( - infer_item(c.clone(), scope.clone()).item.clone(), - ); - } - __result - }), - params: item.params.clone(), - inferred: if (item.inferred.clone() != None) { - item.inferred.clone() - } else { - Some(Rc::new(InferredNode::Resolved { node: unit_type() })) - }, - return_cardinality: item.return_cardinality.clone(), - uses: item.uses.clone(), - body: None, - connective: item.connective.clone(), - transport: typed_transport, - properties: typed_properties, - type_annotation: typed_anno, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }), - diagnostics: v2_rt::concat(transport_diags, props_diags), - }) + None } } + }, + ), + } +} + +pub fn carrier_closure_direct_type_deps( + n: Rc, + dep_env: Rc, + source_indices: Rc>>, +) -> Rc> { + let n_name = authored_name_at(source_indices.clone(), n.clone()); + let authored_ref = if (((n.ident_span.clone() != None) + && (n_name.clone().as_str() != "".to_string().as_str())) + && (is_kernel_type(n_name.clone()) == false)) + { + Rc::new(vec![n_name.clone()]) + } else { + Rc::new(vec![]) + }; + let decl_ref = match n.binding_id.clone() { + Some(binding_id) => match v2_rt::map_get(&dep_env.decl_registry.clone(), binding_id) { + Some(decl) => { + if (((decl.name.clone().as_str() != "".to_string().as_str()) + && (decl.name.clone().as_str() != n_name.as_str())) + && (is_kernel_type(decl.name.clone()) == false)) + { + Rc::new(vec![decl.name.clone()]) + } else { + Rc::new(vec![]) } } - } - }) + None => Rc::new(vec![]), + }, + None => Rc::new(vec![]), + }; + v2_rt::concat( + v2_rt::concat(authored_ref, decl_ref), + node_type_deps(n.clone(), source_indices.clone()), + ) } -pub fn infer_items( - items: Rc>>, - scope: Rc, -) -> Rc>> { - Rc::new({ - let mut __result = Vec::new(); - for item in items.iter().cloned() { - __result.push(infer_item(item.clone(), scope.clone())); +pub fn carrier_closure_node_type_deps( + n: Rc, + dep_env: Rc, + source_indices: Rc>>, +) -> Rc> { + let base = carrier_closure_direct_type_deps(n.clone(), dep_env.clone(), source_indices.clone()); + let child_deps = if n.connective.clone() == Connective::Conj { + Rc::new({ + let mut __result = Vec::new(); + for child in n.children.clone().iter().cloned() { + __result.extend( + (*carrier_closure_node_type_deps( + field_node_type_expr(child.clone()), + dep_env.clone(), + source_indices.clone(), + )) + .clone(), + ); + } + __result + }) + } else { + Rc::new({ + let mut __result = Vec::new(); + for child in n.children.clone().iter().cloned() { + __result.extend( + (*carrier_closure_node_type_deps( + child.clone(), + dep_env.clone(), + source_indices.clone(), + )) + .clone(), + ); + } + __result + }) + }; + v2_rt::concat(base, child_deps) +} + +pub fn add_type_binding_dependency_closure( + state: Rc, + binding: Rc, + dep_env: Rc, + source_indices: Rc>>, +) -> Rc { + stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { + let already_seen = match binding.resolved.clone().binding_id.clone() { + Some(binding_id) => { + v2_rt::map_contains_key(&state.seen_binding_ids.clone(), binding_id) + } + None => v2_rt::map_contains_key(&state.seen_names.clone(), binding.name.clone()), + }; + if already_seen { + state.clone() + } else { + { + let stamped = stamp_type_binding_dependency_refs( + binding.clone(), + dep_env.clone(), + source_indices.clone(), + ); + let with_binding = match stamped.resolved.clone().binding_id.clone() { + Some(binding_id) => Rc::new(CarrierClosureState { + carrier_bindings: v2_rt::rc_map_insert( + state.carrier_bindings.clone(), + binding_id.clone(), + carrier_authority_binding( + stamped.clone(), + dep_env.clone(), + source_indices.clone(), + ), + ), + seen_names: v2_rt::rc_map_insert( + state.seen_names.clone(), + stamped.name.clone(), + true, + ), + seen_binding_ids: v2_rt::rc_map_insert( + state.seen_binding_ids.clone(), + binding_id.clone(), + true, + ), + }), + None => Rc::new(CarrierClosureState { + carrier_bindings: state.carrier_bindings.clone(), + seen_names: v2_rt::rc_map_insert( + state.seen_names.clone(), + stamped.name.clone(), + true, + ), + seen_binding_ids: state.seen_binding_ids.clone(), + }), + }; + let with_decl_binding = + match type_binding_decl_binding_id(dep_env.clone(), binding.clone()) { + Some(decl_binding_id) => Rc::new(CarrierClosureState { + carrier_bindings: v2_rt::rc_map_insert( + with_binding.carrier_bindings.clone(), + decl_binding_id.clone(), + carrier_authority_binding( + stamped.clone(), + dep_env.clone(), + source_indices.clone(), + ), + ), + seen_names: with_binding.seen_names.clone(), + seen_binding_ids: v2_rt::rc_map_insert( + with_binding.seen_binding_ids.clone(), + decl_binding_id.clone(), + true, + ), + }), + None => with_binding.clone(), + }; + let deps = v2_rt::concat( + carrier_closure_node_type_deps( + binding.resolved.clone(), + dep_env.clone(), + source_indices.clone(), + ), + carrier_closure_node_type_deps( + stamped.resolved.clone(), + dep_env.clone(), + source_indices.clone(), + ), + ); + deps.iter().cloned().fold( + with_decl_binding, + |acc: Rc, dep_name: String| { + match lookup_type_binding_by_name_in_env(dep_env.clone(), dep_name.clone()) + { + Some(dep_binding) => add_type_binding_dependency_closure( + acc.clone(), + dep_binding.clone(), + dep_env.clone(), + source_indices.clone(), + ), + None => acc.clone(), + } + }, + ) + } } - __result }) } -pub fn is_type_variable_name(name: String) -> bool { - (((((name.clone().as_str() == "T".to_string().as_str()) - || (name.clone().as_str() == "K".to_string().as_str())) - || (name.clone().as_str() == "V".to_string().as_str())) - || (name.clone().as_str() == "MappedElement".to_string().as_str())) - || (name.clone().as_str() == "FoldAccumulator".to_string().as_str())) -} - -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct ArgGenericFoldState { - pub results: Rc>>, - pub subst: Rc>>, -} - -pub fn param_is_generic_decl( - p: Rc, +pub fn add_node_dependency_closure( + state: Rc, + n: Rc, + dep_env: Rc, source_indices: Rc>>, -) -> bool { +) -> Rc { { - let pt = param_node_type_expr(p.clone()); - let pname = param_node_name_at(p.clone(), source_indices.clone()); - let tname = authored_name_at(source_indices.clone(), pt.clone()); - ((((pt.children.clone().len() as i64) == 0) - && (pt.connective.clone() == Connective::NoConnective)) - && ((pname.clone().as_str() != "".to_string().as_str()) - && (pname.clone().as_str() == tname.as_str()))) + let stamped = + stamp_hidden_dependency_refs(n.clone(), dep_env.clone(), source_indices.clone()); + let name = authored_name_at(source_indices.clone(), stamped.clone()); + let with_self = if (name.clone().as_str() != "".to_string().as_str()) { + match lookup_type_binding_by_name_in_env(dep_env.clone(), name.clone()) { + Some(self_binding) => add_type_binding_dependency_closure( + state, + self_binding.clone(), + dep_env.clone(), + source_indices.clone(), + ), + None => state, + } + } else { + state + }; + let deps = v2_rt::concat( + carrier_closure_node_type_deps(n.clone(), dep_env.clone(), source_indices.clone()), + carrier_closure_node_type_deps( + stamped.clone(), + dep_env.clone(), + source_indices.clone(), + ), + ); + deps.iter().cloned().fold( + with_self, + |acc: Rc, dep_name: String| { + match lookup_type_binding_by_name_in_env(dep_env.clone(), dep_name.clone()) { + Some(dep_binding) => add_type_binding_dependency_closure( + acc.clone(), + dep_binding.clone(), + dep_env.clone(), + source_indices.clone(), + ), + None => acc.clone(), + } + }, + ) } } -pub fn unify_generics( - mut formal: Rc, - mut actual: Rc, - mut generic_names: Rc>, - mut source_indices: Rc>>, - mut acc: Rc>>, -) -> Rc>> { - loop { - let fname = authored_name_at(source_indices.clone(), formal.clone()); - let f_bare = (((formal.children.clone().len() as i64) == 0) - && (formal.connective.clone() == Connective::NoConnective)); - if (f_bare && { - let mut __found = false; - for g in generic_names.clone().iter().cloned() { - if (g.clone().as_str() == fname.clone().as_str()) { - __found = true; - break; - } - } - __found - }) { - match v2_rt::map_get(&acc, fname.clone()) { - None => { - break v2_rt::rc_map_insert(acc.clone(), fname.clone(), actual.clone()); - } - Some(_) => { - break acc.clone(); - } - } - } else { - if (((formal.children.clone().len() as i64) == 1) - && ((actual.children.clone().len() as i64) == 1)) - { - match formal.children.clone().first().cloned() { - Some(fc) => match actual.children.clone().first().cloned() { - Some(ac) => { - let __tco_0 = fc.clone(); - let __tco_1 = ac.clone(); - formal = __tco_0; - actual = __tco_1; - continue; - } - None => { - break acc.clone(); +pub fn carrier_closure_with_decl_rows( + state: Rc, + env: Rc, +) -> Rc { + Rc::new(v2_rt::map_values(&env.decl_registry.clone())) + .iter() + .cloned() + .fold( + state, + |acc: Rc, decl: Rc| { + if (v2_rt::map_contains_key(&acc.seen_names.clone(), decl.name.clone()) + && !v2_rt::map_contains_key( + &acc.carrier_bindings.clone(), + decl.binding_id.clone(), + )) + { + { + let binding_for_decl = + match v2_rt::map_get(&env.bindings.clone(), decl.binding_key.clone()) { + Some(binding) => Some(binding.clone()), + None => Rc::new({ + let mut __result = Vec::new(); + for binding in Rc::new(v2_rt::map_values(&env.bindings.clone())) + .iter() + .cloned() + { + if (binding.name.clone().as_str() + == decl.name.clone().as_str()) + { + __result.push(binding); + } + } + __result + }) + .first() + .cloned(), + }; + match binding_for_decl.clone() { + Some(binding) => Rc::new(CarrierClosureState { + carrier_bindings: v2_rt::rc_map_insert( + acc.carrier_bindings.clone(), + decl.binding_id.clone(), + carrier_authority_binding( + binding.clone(), + env.clone(), + env.source_indices.clone(), + ), + ), + seen_names: acc.seen_names.clone(), + seen_binding_ids: v2_rt::rc_map_insert( + acc.seen_binding_ids.clone(), + decl.binding_id.clone(), + true, + ), + }), + None => acc.clone(), } - }, - None => { - break acc.clone(); } + } else { + acc.clone() } - } else { - break acc.clone(); - } - } + }, + ) +} + +pub fn collect_import_carrier_bindings_for_import( + acc: Rc>>, + imp: Rc, + env: Rc, +) -> Rc>> { + { + let closure_state = Rc::new(v2_rt::map_values(&env.bindings.clone())) + .iter() + .cloned() + .fold( + Rc::new(CarrierClosureState { + carrier_bindings: acc, + seen_names: v2_rt::rc_empty_map::(), + seen_binding_ids: v2_rt::rc_empty_map::(), + }), + |state: Rc, binding: Rc| { + if ((imp.module_path.clone().as_str() == "std.types".to_string().as_str()) + && is_type_variable_name(binding.name.clone())) + { + state.clone() + } else { + if import_allows_type_binding(imp.clone(), binding.clone(), env.clone()) { + add_type_binding_dependency_closure( + state.clone(), + binding.clone(), + env.clone(), + env.source_indices.clone(), + ) + } else { + state.clone() + } + } + }, + ); + carrier_closure_with_decl_rows(closure_state, env.clone()) + .carrier_bindings + .clone() } } -pub fn substitute_generics( - n: Rc, - subst: Rc>>, - source_indices: Rc>>, -) -> Rc { - stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { - if ((Rc::new(v2_rt::map_keys(&subst)).len() as i64) == 0) { - n.clone() - } else { - { - let nm = authored_name_at(source_indices.clone(), n.clone()); - let is_bare = ((((n.children.clone().len() as i64) == 0) - && (n.connective.clone() == Connective::NoConnective)) - && ((n.params.clone().len() as i64) == 0)); - if is_bare { - match v2_rt::map_get(&subst, nm) { - Some(c) => c.clone(), - None => n.clone(), +pub fn collect_import_carrier_bindings_for_imported_funcs( + acc: Rc>>, + imp: Rc, + typed_parent: Rc, +) -> Rc>> { + { + let env = typed_parent.type_env.clone(); + let closure_state = Rc::new(v2_rt::map_values( + &typed_parent.func_env.clone().signatures.clone(), + )) + .iter() + .cloned() + .fold( + Rc::new(CarrierClosureState { + carrier_bindings: acc, + seen_names: v2_rt::rc_empty_map::(), + seen_binding_ids: v2_rt::rc_empty_map::(), + }), + |state: Rc, sig: Rc| { + if import_allows_binding_name(imp.clone(), sig.name.clone()) { + { + let with_return = add_node_dependency_closure( + state.clone(), + sig.inferred.clone(), + env.clone(), + env.source_indices.clone(), + ); + sig.params.clone().iter().cloned().fold( + with_return.clone(), + |pacc: Rc, param: Rc| { + add_node_dependency_closure( + pacc, + param_node_type_expr(param.clone()), + env.clone(), + env.source_indices.clone(), + ) + }, + ) } } else { - Rc::new(Node { - name: n.name.clone(), - span: n.span.clone(), - ident_span: n.ident_span.clone(), - children: Rc::new({ - let mut __result = Vec::new(); - for c in n.children.clone().iter().cloned() { - __result.push(substitute_generics( - c.clone(), - subst.clone(), - source_indices.clone(), - )); - } - __result - }), - connective: n.connective.clone(), - params: Rc::new({ - let mut __result = Vec::new(); - for p in n.params.clone().iter().cloned() { - __result.push(substitute_generics( - p.clone(), - subst.clone(), - source_indices.clone(), - )); - } - __result - }), - inferred: match n.inferred.clone().as_deref().cloned() { - Some(InferredNode::Resolved { node: rt, .. }) => { - Some(Rc::new(InferredNode::Resolved { - node: substitute_generics( - rt.clone(), - subst.clone(), - source_indices.clone(), - ), - })) - } - _ => n.inferred.clone(), - }, - return_cardinality: n.return_cardinality.clone(), - uses: n.uses.clone(), - body: n.body.clone(), - transport: n.transport.clone(), - properties: n.properties.clone(), - type_annotation: n.type_annotation.clone(), - is_self_recursive: n.is_self_recursive.clone(), - has_non_tail_self_call: n.has_non_tail_self_call.clone(), - match_pattern: n.match_pattern.clone(), - expr_data: n.expr_data.clone(), - ident: None, - }) + state.clone() } + }, + ); + carrier_closure_with_decl_rows(closure_state, env.clone()) + .carrier_bindings + .clone() + } +} + +pub fn import_allows_binding_name(imp: Rc, name: String) -> bool { + ((imp.is_all.clone() || ((imp.specific_names.clone().len() as i64) == 0)) || { + let mut __found = false; + for n in imp.specific_names.clone().iter().cloned() { + if (n.clone().as_str() == name.clone().as_str()) { + __found = true; + break; } } + __found }) } -pub fn collect_parent_bindings_filtered( - envs: Rc>>, +pub fn import_allows_type_binding( + imp: Rc, + binding: Rc, + env: Rc, +) -> bool { + if import_allows_binding_name(imp.clone(), binding.name.clone()) { + true + } else { + { + let allowed_child = { + let mut __found = false; + for child in binding.resolved.clone().children.clone().iter().cloned() { + if { + let child_name = + authored_name_at(env.source_indices.clone(), child.clone()); + { + let mut __found = false; + for n in imp.specific_names.clone().iter().cloned() { + if (n.clone().as_str() == child_name.clone().as_str()) { + __found = true; + break; + } + } + __found + } + } { + __found = true; + break; + } + } + __found + }; + ((binding.resolved.clone().connective.clone() == Connective::Disj) && allowed_child) + } + } +} + +pub fn collect_import_bindings_for_import( + acc: Rc>>, + imp: Rc, + env: Rc, ) -> Rc>> { - envs.iter().cloned().fold( - v2_rt::rc_empty_map::>(), - |acc: Rc>>, env: Rc| { - Rc::new(v2_rt::map_keys(&env.bindings.clone())) - .iter() - .cloned() - .fold( - acc, - |bacc: Rc>>, ident: i64| { - let name = intern_str(env.intern_table.clone(), ident.clone()); - if is_type_variable_name(name.clone()) { + Rc::new(v2_rt::map_keys(&env.bindings.clone())) + .iter() + .cloned() + .fold( + acc, + |bacc: Rc>>, ident: i64| { + let name = intern_str(env.intern_table.clone(), ident.clone()); + match v2_rt::map_get(&env.bindings.clone(), ident.clone()) { + Some(binding) => { + if ((imp.module_path.clone().as_str() == "std.types".to_string().as_str()) + && is_type_variable_name(name.clone())) + { bacc.clone() } else { - match v2_rt::map_get(&env.bindings.clone(), ident.clone()) { - Some(binding) => v2_rt::rc_map_insert( + if import_allows_type_binding(imp.clone(), binding.clone(), env.clone()) + { + v2_rt::rc_map_insert( bacc.clone(), ident.clone(), - binding.clone(), - ), - None => bacc.clone(), + stamp_type_binding_dependency_refs( + binding.clone(), + env.clone(), + env.source_indices.clone(), + ), + ) + } else { + bacc.clone() } } - }, - ) - }, - ) + } + None => bacc.clone(), + } + }, + ) +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct TypeDeclRegistrationAccum { + pub bindings: Rc>>, + pub decl_registry: Rc>>, + pub allocator: BindingIdAllocator, +} + +pub fn register_type_decl_binding( + acc: Rc, + item_ident: i64, + name: String, + module_name: String, + decl_span: Rc, + resolved: Rc, + provenance: Rc, +) -> Rc { + { + let binding_alloc = alloc_binding_id(acc.allocator.clone()); + let stamped = node_with_binding_id(resolved.clone(), binding_alloc.binding_id.clone()); + Rc::new(TypeDeclRegistrationAccum { + bindings: v2_rt::rc_map_insert( + acc.bindings.clone(), + item_ident.clone(), + Rc::new(TypeBinding { + name: name.clone(), + resolved: stamped, + provenance: provenance.clone(), + }), + ), + decl_registry: v2_rt::rc_map_insert( + acc.decl_registry.clone(), + binding_alloc.binding_id.clone(), + Rc::new(TypeDeclBinding { + binding_id: binding_alloc.binding_id.clone(), + authority: Rc::new(TypeDeclAuthority { + module_name: module_name, + decl_name: name.clone(), + decl_span: decl_span, + }), + binding_key: item_ident.clone(), + decl_arity: (resolved.params.clone().len() as i64), + name: name.clone(), + provenance: provenance.clone(), + }), + ), + allocator: binding_alloc.allocator.clone(), + }) + } } pub fn kernel_span(name: String) -> Rc { @@ -10646,6 +12696,7 @@ pub fn build_type_env( parent_index: Rc>>, source_indices: Rc>>, intern_table: Rc, + allocator: BindingIdAllocator, ) -> Rc { { let source_indices = Rc::new(v2_rt::map_keys(&kernel_type_set())) @@ -10752,6 +12803,7 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), provenance: Rc::new(SubValueRelation::SubValueUnknown), }), @@ -10783,6 +12835,7 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), provenance: Rc::new(SubValueRelation::SubValueUnknown), }), @@ -10808,6 +12861,7 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let present_variant = Rc::new(Node { name: "Present".to_string(), @@ -10828,6 +12882,7 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let absent_variant = Rc::new(Node { name: "Absent".to_string(), @@ -10848,6 +12903,7 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let kernel_optional = Rc::new(Node { name: "Optional".to_string(), @@ -10868,6 +12924,7 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let kernel_bindings = v2_rt::rc_map_insert( kernel_bindings.clone(), @@ -10906,6 +12963,9 @@ pub fn build_type_env( ); let kernel = Rc::new(TypeEnv { bindings: kernel_bindings.clone(), + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: v2_rt::rc_empty_map::>(), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: kernel_recursive_types, recursive_type_set: kernel_recursive_type_set, inductive_fields: node_fields, @@ -10956,45 +13016,31 @@ pub fn build_type_env( &parent_index, imp.module_path.clone(), ) { - Some(typed_parent) => { - if (imp.module_path.clone().as_str() == "std.types".to_string().as_str()) { - Rc::new(v2_rt::map_keys( - &typed_parent.type_env.clone().bindings.clone(), - )) - .iter() - .cloned() - .fold( - acc.clone(), - |bacc: Rc>>, ident: i64| { - let name = intern_str( - typed_parent.type_env.clone().intern_table.clone(), - ident.clone(), - ); - if is_type_variable_name(name.clone()) { - bacc.clone() - } else { - match v2_rt::map_get( - &typed_parent.type_env.clone().bindings.clone(), - ident.clone(), - ) { - Some(binding) => v2_rt::rc_map_insert( - bacc.clone(), - ident.clone(), - binding.clone(), - ), - None => bacc.clone(), - } - } - }, - ) - } else { - v2_rt::rc_map_merge( + Some(typed_parent) => collect_import_bindings_for_import( + acc.clone(), + imp.clone(), + typed_parent.type_env.clone(), + ), + None => acc.clone(), + }, + ); + let std_import_carrier_bindings = + collect_parent_carrier_bindings(std_types_parent_env.clone()); + let import_carrier_bindings = module.resolved_imports.clone().iter().cloned().fold( + std_import_carrier_bindings, + |acc: Rc>>, imp: Rc| { + match v2_rt::map_get(&parent_index, imp.module_path.clone()) { + Some(typed_parent) => collect_import_carrier_bindings_for_imported_funcs( + collect_import_carrier_bindings_for_import( acc.clone(), - typed_parent.type_env.clone().bindings.clone(), - ) - } + imp.clone(), + typed_parent.type_env.clone(), + ), + imp.clone(), + typed_parent.clone(), + ), + None => acc.clone(), } - None => acc.clone(), }, ); let import_recursive = parent_envs @@ -11004,6 +13050,39 @@ pub fn build_type_env( .fold(Rc::new(vec![]), |acc: _, env: Rc| { v2_rt::concat(acc, env.recursive_types.clone()) }); + let import_decl_state = + parent_envs.clone().iter().cloned().fold( + Rc::new(TypeEnv { + bindings: v2_rt::rc_empty_map::>(), + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: v2_rt::rc_empty_map::>(), + duplicate_decl_ids: Rc::new(vec![]), + recursive_types: Rc::new(vec![]), + recursive_type_set: v2_rt::rc_empty_map::(), + inductive_fields: v2_rt::rc_empty_map::>>>(), + source_indices: source_indices.clone(), + intern_table: intern_table.clone(), + }), + |acc: Rc, env: Rc| { + merge_envs(Rc::new(vec![ + acc, + Rc::new(TypeEnv { + bindings: v2_rt::rc_empty_map::>(), + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: env.decl_registry.clone(), + duplicate_decl_ids: env.duplicate_decl_ids.clone(), + recursive_types: Rc::new(vec![]), + recursive_type_set: v2_rt::rc_empty_map::(), + inductive_fields: v2_rt::rc_empty_map::< + String, + Rc>>, + >(), + source_indices: source_indices.clone(), + intern_table: intern_table.clone(), + }), + ])) + }, + ); let import_recursive_set = parent_envs.clone().iter().cloned().fold( v2_rt::rc_empty_map::(), |acc: Rc>, env: Rc| { @@ -11018,6 +13097,9 @@ pub fn build_type_env( ); let import_env = Rc::new(TypeEnv { bindings: import_bindings, + carrier_bindings: import_carrier_bindings, + decl_registry: import_decl_state.decl_registry.clone(), + duplicate_decl_ids: import_decl_state.duplicate_decl_ids.clone(), recursive_types: import_recursive, recursive_type_set: import_recursive_set, inductive_fields: import_inductive_fields, @@ -11057,16 +13139,31 @@ pub fn build_type_env( } __result }); - let local_bindings = module_items(module.module.clone()).iter().cloned().fold( - v2_rt::rc_empty_map::>(), - |acc: Rc>>, item: Rc| { + let local_registration = module_items(module.module.clone()).iter().cloned().fold( + Rc::new(TypeDeclRegistrationAccum { + bindings: v2_rt::rc_empty_map::>(), + decl_registry: v2_rt::rc_empty_map::>(), + allocator: allocator.clone(), + }), + |acc: Rc, item: Rc| { let item_ident = intern( intern_table.clone(), authored_name_at(source_indices.clone(), item.clone()), ) .id .clone(); + let item_name = authored_name_at(source_indices.clone(), item.clone()); let has_structure = (item.connective.clone() != Connective::NoConnective); + let params_are_generic_decls = { + let mut __all = true; + for p in item.params.clone().iter().cloned() { + if !(param_is_generic_decl(p.clone(), source_indices.clone())) { + __all = false; + break; + } + } + __all + }; if has_structure.clone() { { let type_node = Rc::new(Node { @@ -11088,21 +13185,22 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); - v2_rt::rc_map_insert( + register_type_decl_binding( acc.clone(), item_ident.clone(), - Rc::new(TypeBinding { - name: authored_name_at(source_indices.clone(), item.clone()), - resolved: type_node.clone(), - provenance: Rc::new(SubValueRelation::SubValueUnknown), - }), + item_name.clone(), + module_name_str.clone(), + item.span.clone(), + type_node.clone(), + Rc::new(SubValueRelation::SubValueUnknown), ) } } else { - if (((item.inferred.clone() != None) - && ((item.params.clone().len() as i64) == 0)) - && (item.body.clone() == None)) + if (((item.inferred.clone() != None) && (item.body.clone() == None)) + && (((item.params.clone().len() as i64) == 0) + || (params_are_generic_decls.clone() == false))) { { let alias_node = Rc::new(Node { @@ -11124,15 +13222,16 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); - v2_rt::rc_map_insert( + register_type_decl_binding( acc.clone(), item_ident.clone(), - Rc::new(TypeBinding { - name: authored_name_at(source_indices.clone(), item.clone()), - resolved: alias_node.clone(), - provenance: Rc::new(SubValueRelation::SubValueUnknown), - }), + item_name.clone(), + module_name_str.clone(), + item.span.clone(), + alias_node.clone(), + Rc::new(SubValueRelation::SubValueUnknown), ) } } else { @@ -11145,21 +13244,19 @@ pub fn build_type_env( item.span.clone(), item.ident_span.clone(), ); - v2_rt::rc_map_insert( + register_type_decl_binding( acc.clone(), item_ident.clone(), - Rc::new(TypeBinding { - name: authored_name_at( - source_indices.clone(), - item.clone(), - ), - resolved: ref_node.clone(), - provenance: Rc::new(SubValueRelation::SubValueUnknown), - }), + item_name.clone(), + module_name_str.clone(), + item.span.clone(), + ref_node.clone(), + Rc::new(SubValueRelation::SubValueUnknown), ) } } else { - if (((((item.params.clone().len() as i64) > 0) + if ((((((item.params.clone().len() as i64) > 0) + && params_are_generic_decls.clone()) && (item.connective.clone() == Connective::NoConnective)) && (item.body.clone() == None)) && (item.transport.clone() == None)) @@ -11184,18 +13281,16 @@ pub fn build_type_env( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); - v2_rt::rc_map_insert( + register_type_decl_binding( acc.clone(), item_ident.clone(), - Rc::new(TypeBinding { - name: authored_name_at( - source_indices.clone(), - item.clone(), - ), - resolved: bare_node.clone(), - provenance: Rc::new(SubValueRelation::SubValueUnknown), - }), + item_name.clone(), + module_name_str.clone(), + item.span.clone(), + bare_node.clone(), + Rc::new(SubValueRelation::SubValueUnknown), ) } } else { @@ -11205,13 +13300,14 @@ pub fn build_type_env( && (item.inferred.clone() == None)) && ((item.params.clone().len() as i64) == 0)) { - v2_rt::rc_map_insert( + register_type_decl_binding( acc.clone(), item_ident.clone(), - nominal_type_binding(authored_name_at( - source_indices.clone(), - item.clone(), - )), + item_name.clone(), + module_name_str.clone(), + item.span.clone(), + nominal_leaf_type(item_name.clone()), + Rc::new(SubValueRelation::SubValueUnknown), ) } else { acc.clone() @@ -11222,6 +13318,9 @@ pub fn build_type_env( } }, ); + let local_bindings = local_registration.bindings.clone(); + let local_decl_registry = local_registration.decl_registry.clone(); + let allocator = local_registration.allocator.clone(); let param_bindings = module_items(module.module.clone()).iter().cloned().fold( v2_rt::rc_empty_map::>(), |acc: Rc>>, item: Rc| { @@ -11276,6 +13375,9 @@ pub fn build_type_env( let all_local_bindings = v2_rt::rc_map_merge(local_bindings.clone(), param_bindings); let pre_local_env = Rc::new(TypeEnv { bindings: all_local_bindings, + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: local_decl_registry, + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: v2_rt::rc_empty_map::(), inductive_fields: v2_rt::rc_empty_map::>>>(), @@ -11341,8 +13443,24 @@ pub fn build_type_env( ); let merged_inductive_fields = merge_inductive_fields(merged.inductive_fields.clone(), local_inductive_fields); + let duplicate_decl_diags = Rc::new({ + let mut __result = Vec::new(); + for _ in merged.duplicate_decl_ids.clone().iter().cloned() { + __result.push(make_error_node( + Rc::new(CompilerDiagnostic::InternalError { + message: "duplicate BindingId in TypeEnv merge".to_string(), + span: module.module.clone().span.clone(), + }), + module_name_str.clone(), + )); + } + __result + }); let unresolved_env = Rc::new(TypeEnv { bindings: merged.bindings.clone(), + carrier_bindings: merged.carrier_bindings.clone(), + decl_registry: merged.decl_registry.clone(), + duplicate_decl_ids: merged.duplicate_decl_ids.clone(), recursive_types: cycle_set, recursive_type_set: cross_type_set, inductive_fields: merged_inductive_fields, @@ -11359,6 +13477,9 @@ pub fn build_type_env( let resolved_diags = resolved.diagnostics.clone(); let final_env = Rc::new(TypeEnv { bindings: resolved_env_out.bindings.clone(), + carrier_bindings: resolved_env_out.carrier_bindings.clone(), + decl_registry: resolved_env_out.decl_registry.clone(), + duplicate_decl_ids: resolved_env_out.duplicate_decl_ids.clone(), recursive_types: resolved_env_out.recursive_types.clone(), recursive_type_set: resolved_env_out.recursive_type_set.clone(), inductive_fields: resolved_env_out.inductive_fields.clone(), @@ -11367,7 +13488,11 @@ pub fn build_type_env( }); Rc::new(BuildTypeEnvResult { env: final_env, - diagnostics: v2_rt::concat(import_diags, resolved_diags), + allocator: allocator.clone(), + diagnostics: v2_rt::concat( + v2_rt::concat(import_diags, duplicate_decl_diags), + resolved_diags, + ), }) } } @@ -11422,6 +13547,7 @@ pub fn build_type_env_unresolved( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), provenance: Rc::new(SubValueRelation::SubValueUnknown), }), @@ -11449,6 +13575,7 @@ pub fn build_type_env_unresolved( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let present_variant = Rc::new(Node { name: "Present".to_string(), @@ -11469,6 +13596,7 @@ pub fn build_type_env_unresolved( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let absent_variant = Rc::new(Node { name: "Absent".to_string(), @@ -11489,6 +13617,7 @@ pub fn build_type_env_unresolved( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let kernel_optional = Rc::new(Node { name: "Optional".to_string(), @@ -11509,6 +13638,7 @@ pub fn build_type_env_unresolved( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let kernel_bindings = v2_rt::rc_map_insert( kernel_bindings.clone(), @@ -11523,6 +13653,9 @@ pub fn build_type_env_unresolved( ); let kernel = Rc::new(TypeEnv { bindings: kernel_bindings.clone(), + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: v2_rt::rc_empty_map::>(), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: v2_rt::rc_empty_map::(), inductive_fields: v2_rt::rc_empty_map::>>>(), @@ -11573,45 +13706,31 @@ pub fn build_type_env_unresolved( &parent_index, imp.module_path.clone(), ) { - Some(typed_parent) => { - if (imp.module_path.clone().as_str() == "std.types".to_string().as_str()) { - Rc::new(v2_rt::map_keys( - &typed_parent.type_env.clone().bindings.clone(), - )) - .iter() - .cloned() - .fold( - acc.clone(), - |bacc: Rc>>, ident: i64| { - let name = intern_str( - typed_parent.type_env.clone().intern_table.clone(), - ident.clone(), - ); - if is_type_variable_name(name.clone()) { - bacc.clone() - } else { - match v2_rt::map_get( - &typed_parent.type_env.clone().bindings.clone(), - ident.clone(), - ) { - Some(binding) => v2_rt::rc_map_insert( - bacc.clone(), - ident.clone(), - binding.clone(), - ), - None => bacc.clone(), - } - } - }, - ) - } else { - v2_rt::rc_map_merge( + Some(typed_parent) => collect_import_bindings_for_import( + acc.clone(), + imp.clone(), + typed_parent.type_env.clone(), + ), + None => acc.clone(), + }, + ); + let std_import_carrier_bindings = + collect_parent_carrier_bindings(std_types_parent_env.clone()); + let import_carrier_bindings = module.resolved_imports.clone().iter().cloned().fold( + std_import_carrier_bindings, + |acc: Rc>>, imp: Rc| { + match v2_rt::map_get(&parent_index, imp.module_path.clone()) { + Some(typed_parent) => collect_import_carrier_bindings_for_imported_funcs( + collect_import_carrier_bindings_for_import( acc.clone(), - typed_parent.type_env.clone().bindings.clone(), - ) - } + imp.clone(), + typed_parent.type_env.clone(), + ), + imp.clone(), + typed_parent.clone(), + ), + None => acc.clone(), } - None => acc.clone(), }, ); let import_recursive = parent_envs @@ -11621,6 +13740,39 @@ pub fn build_type_env_unresolved( .fold(Rc::new(vec![]), |acc: _, env: Rc| { v2_rt::concat(acc, env.recursive_types.clone()) }); + let import_decl_state = + parent_envs.clone().iter().cloned().fold( + Rc::new(TypeEnv { + bindings: v2_rt::rc_empty_map::>(), + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: v2_rt::rc_empty_map::>(), + duplicate_decl_ids: Rc::new(vec![]), + recursive_types: Rc::new(vec![]), + recursive_type_set: v2_rt::rc_empty_map::(), + inductive_fields: v2_rt::rc_empty_map::>>>(), + source_indices: source_indices.clone(), + intern_table: intern_table.clone(), + }), + |acc: Rc, env: Rc| { + merge_envs(Rc::new(vec![ + acc, + Rc::new(TypeEnv { + bindings: v2_rt::rc_empty_map::>(), + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: env.decl_registry.clone(), + duplicate_decl_ids: env.duplicate_decl_ids.clone(), + recursive_types: Rc::new(vec![]), + recursive_type_set: v2_rt::rc_empty_map::(), + inductive_fields: v2_rt::rc_empty_map::< + String, + Rc>>, + >(), + source_indices: source_indices.clone(), + intern_table: intern_table.clone(), + }), + ])) + }, + ); let import_recursive_set = parent_envs.clone().iter().cloned().fold( v2_rt::rc_empty_map::(), |acc: Rc>, env: Rc| { @@ -11635,6 +13787,9 @@ pub fn build_type_env_unresolved( ); let import_env = Rc::new(TypeEnv { bindings: import_bindings, + carrier_bindings: import_carrier_bindings, + decl_registry: import_decl_state.decl_registry.clone(), + duplicate_decl_ids: import_decl_state.duplicate_decl_ids.clone(), recursive_types: import_recursive, recursive_type_set: import_recursive_set, inductive_fields: import_inductive_fields, @@ -11651,6 +13806,16 @@ pub fn build_type_env_unresolved( .id .clone(); let has_structure = (item.connective.clone() != Connective::NoConnective); + let params_are_generic_decls = { + let mut __all = true; + for p in item.params.clone().iter().cloned() { + if !(param_is_generic_decl(p.clone(), source_indices.clone())) { + __all = false; + break; + } + } + __all + }; if has_structure.clone() { { let type_node = Rc::new(Node { @@ -11672,6 +13837,7 @@ pub fn build_type_env_unresolved( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); v2_rt::rc_map_insert( acc.clone(), @@ -11684,9 +13850,9 @@ pub fn build_type_env_unresolved( ) } } else { - if (((item.inferred.clone() != None) - && ((item.params.clone().len() as i64) == 0)) - && (item.body.clone() == None)) + if (((item.inferred.clone() != None) && (item.body.clone() == None)) + && (((item.params.clone().len() as i64) == 0) + || (params_are_generic_decls.clone() == false))) { { let alias_node = Rc::new(Node { @@ -11708,6 +13874,7 @@ pub fn build_type_env_unresolved( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); v2_rt::rc_map_insert( acc.clone(), @@ -11767,6 +13934,9 @@ pub fn build_type_env_unresolved( ); let pre_local_env = Rc::new(TypeEnv { bindings: local_bindings, + carrier_bindings: v2_rt::rc_empty_map::>(), + decl_registry: v2_rt::rc_empty_map::>(), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: v2_rt::rc_empty_map::(), inductive_fields: v2_rt::rc_empty_map::>>>(), @@ -11834,6 +14004,9 @@ pub fn build_type_env_unresolved( merge_inductive_fields(merged.inductive_fields.clone(), local_inductive_fields); let unresolved_env = Rc::new(TypeEnv { bindings: merged.bindings.clone(), + carrier_bindings: merged.carrier_bindings.clone(), + decl_registry: merged.decl_registry.clone(), + duplicate_decl_ids: merged.duplicate_decl_ids.clone(), recursive_types: cycle_set, recursive_type_set: cross_type_set, inductive_fields: merged_inductive_fields, @@ -11842,6 +14015,7 @@ pub fn build_type_env_unresolved( }); Rc::new(BuildTypeEnvResult { env: unresolved_env, + allocator: empty_binding_id_allocator(), diagnostics: Rc::new(vec![]), }) } @@ -12097,59 +14271,151 @@ pub fn build_module_context( ); let imported_enum_names = resolved_imports.clone().iter().cloned().fold( v2_rt::rc_empty_map::(), - |acc: Rc>, imp: Rc| { - imp.specific_names.clone().iter().cloned().fold( - acc, + |acc: Rc>, imp: Rc| match v2_rt::map_get( + &parent_index, + imp.module_path.clone(), + ) { + Some(typed_parent) => Rc::new(v2_rt::map_values( + &typed_parent.type_env.clone().bindings.clone(), + )) + .iter() + .cloned() + .fold( + acc.clone(), + |inner: Rc>, parent_binding: Rc| { + let parent_name = parent_binding.name.clone(); + if ((parent_binding.resolved.clone().connective.clone() + == Connective::Disj) + && import_allows_binding_name(imp.clone(), parent_name.clone())) + { + v2_rt::rc_map_insert(inner.clone(), parent_name.clone(), true) + } else { + inner.clone() + } + }, + ), + None => acc.clone(), + }, + ); + let imported_variant_parent_names = resolved_imports.clone().iter().cloned().fold( + v2_rt::rc_empty_map::(), + |acc: Rc>, imp: Rc| match v2_rt::map_get( + &parent_index, + imp.module_path.clone(), + ) { + Some(typed_parent) => imp.specific_names.clone().iter().cloned().fold( + acc.clone(), |inner: Rc>, n: String| { - v2_rt::rc_map_insert(inner, n.clone(), true) + Rc::new(v2_rt::map_values( + &typed_parent.type_env.clone().bindings.clone(), + )) + .iter() + .cloned() + .fold( + inner, + |pacc: Rc>, parent_binding: Rc| { + let parent_name = parent_binding.name.clone(); + if (((parent_binding.resolved.clone().connective.clone() + == Connective::Disj) + && (import_allows_binding_name( + imp.clone(), + parent_name.clone(), + ) == false)) + && has_child_named( + parent_binding.resolved.clone(), + n.clone(), + typed_parent.type_env.clone().source_indices.clone(), + )) + { + v2_rt::rc_map_insert( + pacc.clone(), + v2_rt::concat( + v2_rt::concat(parent_name.clone(), "::".to_string()), + n.clone(), + ), + true, + ) + } else { + pacc.clone() + } + }, + ) }, - ) + ), + None => acc.clone(), }, ); let variant_fold = Rc::new(v2_rt::map_values(&env.bindings.clone())).iter().cloned().fold(Rc::new(VariantFoldState { locals: v2_rt::rc_empty_map::>(), - collision_errors: Rc::new(vec![]), + collisions: v2_rt::rc_empty_map::>(), }), |acc: Rc, binding: Rc| { let is_coproduct = (binding.resolved.clone().connective.clone() == Connective::Disj); if is_coproduct.clone() { { - let curr_is_imported = (v2_rt::map_get(&imported_enum_names, authored_name_at(env.source_indices.clone(), binding.resolved.clone())) != None); -binding.resolved.clone().children.clone().iter().cloned().fold(acc.clone(), |vacc: Rc, child: Rc| match v2_rt::map_get(&vacc.locals.clone(), authored_name_at(env.source_indices.clone(), child.clone())) { + let curr_parent_name = authored_name_at(env.source_indices.clone(), binding.resolved.clone()); +let curr_parent_imported = ((curr_parent_name.clone().as_str() == "Optional".to_string().as_str()) || (v2_rt::map_get(&imported_enum_names, curr_parent_name.clone()) != None)); +binding.resolved.clone().children.clone().iter().cloned().fold(acc.clone(), |vacc: Rc, child: Rc| { + let child_name = authored_name_at(env.source_indices.clone(), child.clone()); +let curr_variant_imported = (v2_rt::map_get(&imported_variant_parent_names, v2_rt::concat(v2_rt::concat(curr_parent_name.clone(), "::".to_string()), child_name.clone())) != None); +let curr_is_imported = (curr_parent_imported.clone() || curr_variant_imported.clone()); +match v2_rt::map_get(&vacc.locals.clone(), child_name.clone()) { Some(prev) => { - let prev_is_imported = (v2_rt::map_get(&imported_enum_names, authored_name_at(env.source_indices.clone(), prev.resolved.clone())) != None); -if (curr_is_imported.clone() && prev_is_imported.clone()) { - Rc::new(VariantFoldState { + let prev_parent_name = authored_name_at(env.source_indices.clone(), prev.resolved.clone()); +let prev_parent_imported = (v2_rt::map_get(&imported_enum_names, prev_parent_name.clone()) != None); +let prev_variant_imported = (v2_rt::map_get(&imported_variant_parent_names, v2_rt::concat(v2_rt::concat(prev_parent_name.clone(), "::".to_string()), child_name.clone())) != None); +let prev_is_imported = (prev_parent_imported.clone() || prev_variant_imported.clone()); +let same_parent_binding = match binding.resolved.clone().binding_id.clone() { + Some(curr_binding_id) => match prev.resolved.clone().binding_id.clone() { + Some(prev_binding_id) => ((curr_binding_id.clone() == prev_binding_id.clone()) || match v2_rt::map_get(&env.decl_registry.clone(), curr_binding_id.clone()) { + Some(curr_decl) => match v2_rt::map_get(&env.decl_registry.clone(), prev_binding_id.clone()) { + Some(prev_decl) => (curr_decl.authority.clone() == prev_decl.authority.clone()), + None => false, +}, + None => false, +}), + None => false, +}, + None => (curr_parent_name.clone().as_str() == prev_parent_name.clone().as_str()), +}; +let same_parent_binding = (same_parent_binding.clone() || same_canonical_container_variant_parent(binding.resolved.clone(), prev.resolved.clone(), env.source_indices.clone())); +if (((((((curr_variant_imported.clone() && prev_variant_imported.clone()) && (same_parent_binding.clone() == false)) && (is_bootstrap_duplicate_variant_name(child_name.clone()) == false)) && (curr_parent_imported.clone() == false)) && (prev_parent_imported.clone() == false)) && curr_is_imported.clone()) && prev_is_imported.clone()) { + Rc::new(VariantFoldState { locals: vacc.locals.clone(), - collision_errors: v2_rt::rc_list_push(vacc.collision_errors.clone(), make_error_node(Rc::new(CompilerDiagnostic::VariantCollision { - variant: authored_name_at(env.source_indices.clone(), child.clone()), - enum1: authored_name_at(env.source_indices.clone(), prev.resolved.clone()), - enum2: authored_name_at(env.source_indices.clone(), binding.resolved.clone()), + collisions: v2_rt::rc_map_insert(vacc.collisions.clone(), child_name.clone(), make_error_node(Rc::new(CompilerDiagnostic::VariantCollision { + variant: child_name.clone(), + enum1: prev_parent_name.clone(), + enum2: curr_parent_name.clone(), span: no_span(), }), module_name.clone())), }) - } else { - if curr_is_imported.clone() { - Rc::new(VariantFoldState { - locals: v2_rt::rc_map_insert(vacc.locals.clone(), authored_name_at(env.source_indices.clone(), child.clone()), Rc::new(TypeBinding { - name: authored_name_at(env.source_indices.clone(), child.clone()), + } else { + if (curr_parent_imported.clone() && (prev_parent_imported.clone() == false)) { + Rc::new(VariantFoldState { + locals: v2_rt::rc_map_insert(vacc.locals.clone(), child_name.clone(), Rc::new(TypeBinding { + name: child_name.clone(), resolved: binding.resolved.clone(), provenance: Rc::new(SubValueRelation::SubValueUnknown), })), - collision_errors: vacc.collision_errors.clone(), + collisions: vacc.collisions.clone(), }) - } else { - vacc.clone() + } else { + vacc.clone() + } } - } }, - None => Rc::new(VariantFoldState { - locals: v2_rt::rc_map_insert(vacc.locals.clone(), authored_name_at(env.source_indices.clone(), child.clone()), Rc::new(TypeBinding { - name: authored_name_at(env.source_indices.clone(), child.clone()), + None => if curr_is_imported.clone() { + Rc::new(VariantFoldState { + locals: v2_rt::rc_map_insert(vacc.locals.clone(), child_name.clone(), Rc::new(TypeBinding { + name: child_name.clone(), resolved: binding.resolved.clone(), provenance: Rc::new(SubValueRelation::SubValueUnknown), })), - collision_errors: vacc.collision_errors.clone(), -}), + collisions: vacc.collisions.clone(), +}) + } else { + vacc.clone() + }, +} }) } } else { @@ -12157,7 +14423,7 @@ if (curr_is_imported.clone() && prev_is_imported.clone()) { } }); let imported_variant_locals = variant_fold.locals.clone(); - let variant_collision_errors = variant_fold.collision_errors.clone(); + let variant_collisions = variant_fold.collisions.clone(); let env_variant_locals = variant_locals_from_items( local.resolved_items.clone(), imported_variant_locals, @@ -12165,7 +14431,7 @@ if (curr_is_imported.clone() && prev_is_imported.clone()) { ); let merged_scope = merge_scope_from_imports( resolved_imports.clone(), - parent_index, + parent_index.clone(), env.clone(), v2_rt::rc_empty_map::>(), local.svc_registry.clone(), @@ -12194,18 +14460,16 @@ if (curr_is_imported.clone() && prev_is_imported.clone()) { svc_registry: merged_scope.svc_registry.clone(), locals: all_locals, item_registry: local.item_registry.clone(), + variant_collisions: variant_collisions, diagnostics: v2_rt::concat( - v2_rt::concat( - Rc::new({ - let mut __result = Vec::new(); - for c in local.diag_chunks.clone().iter().cloned() { - __result.extend((*c.clone()).iter().cloned()); - } - __result - }), - resolve_result.diagnostics.clone(), - ), - variant_collision_errors, + Rc::new({ + let mut __result = Vec::new(); + for c in local.diag_chunks.clone().iter().cloned() { + __result.extend((*c.clone()).iter().cloned()); + } + __result + }), + resolve_result.diagnostics.clone(), ), }) } @@ -12214,6 +14478,7 @@ if (curr_is_imported.clone() && prev_is_imported.clone()) { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct TypecheckModuleResult { pub typed: Rc, + pub allocator: BindingIdAllocator, pub diagnostics: Rc>>, } @@ -12222,6 +14487,7 @@ pub fn typecheck_module( parent_index: Rc>>, source_indices: Rc>>, intern_table: Rc, + allocator: BindingIdAllocator, ) -> Rc { { let env_result = build_type_env( @@ -12229,8 +14495,10 @@ pub fn typecheck_module( parent_index.clone(), source_indices.clone(), intern_table, + allocator.clone(), ); let env = env_result.env.clone(); + let allocator = env_result.allocator.clone(); let env_diags = env_result.diagnostics.clone(); let env_errors = Rc::new({ let mut __result = Vec::new(); @@ -12253,6 +14521,7 @@ pub fn typecheck_module( }), item_registry: v2_rt::rc_empty_map::>(), }), + allocator: allocator.clone(), diagnostics: v2_rt::concat(env_diags.clone(), seed_diags.clone()), }); } @@ -12301,6 +14570,7 @@ pub fn typecheck_module( type_env: env.clone(), func_env: ctx.func_env.clone(), locals: data_locals.clone(), + variant_collisions: ctx.variant_collisions.clone(), match_bound_names: v2_rt::rc_empty_map::(), module_name: resolved_module_name.clone(), service_registry: ctx.svc_registry.clone(), @@ -12335,6 +14605,8 @@ pub fn typecheck_module( if (item.is_self_recursive.clone() && (item.body.clone() != None)) { Rc::new(Node { name: item.name.clone(), + ident: item.ident.clone(), + binding_id: item.binding_id.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), children: item.children.clone(), @@ -12358,7 +14630,6 @@ pub fn typecheck_module( has_non_tail_self_call: item.has_non_tail_self_call.clone(), match_pattern: item.match_pattern.clone(), expr_data: item.expr_data.clone(), - ident: None, }) } else { item.clone() @@ -12385,6 +14656,7 @@ pub fn typecheck_module( func_env: updated_func_env.clone(), item_registry: ctx.item_registry.clone(), }), + allocator: allocator.clone(), diagnostics: v2_rt::concat( v2_rt::concat( v2_rt::concat(env_diags.clone(), ctx.diagnostics.clone()), @@ -12549,6 +14821,9 @@ pub fn topo_resolve_types( return Rc::new(EnvResolveResult { env: Rc::new(TypeEnv { bindings: stuck_accum.bindings.clone(), + carrier_bindings: env.carrier_bindings.clone(), + decl_registry: env.decl_registry.clone(), + duplicate_decl_ids: env.duplicate_decl_ids.clone(), recursive_types: env.recursive_types.clone(), recursive_type_set: env.recursive_type_set.clone(), inductive_fields: env.inductive_fields.clone(), @@ -12618,6 +14893,9 @@ pub fn topo_resolve_types( let __tco_0 = next_remaining; let __tco_1 = Rc::new(TypeEnv { bindings: ready_accum.bindings.clone(), + carrier_bindings: env.carrier_bindings.clone(), + decl_registry: env.decl_registry.clone(), + duplicate_decl_ids: env.duplicate_decl_ids.clone(), recursive_types: env.recursive_types.clone(), recursive_type_set: env.recursive_type_set.clone(), inductive_fields: env.inductive_fields.clone(), @@ -12904,6 +15182,7 @@ pub fn typecheck( Rc::new(vec![]), source_indices, intern_table, + empty_binding_id_allocator(), ) } @@ -12915,6 +15194,7 @@ pub fn typecheck_modules( mut diag_chunks: Rc>>>>, mut source_indices: Rc>>, mut intern_table: Rc, + mut allocator: BindingIdAllocator, ) -> Rc { loop { match remaining.clone().first().cloned() { @@ -12944,9 +15224,11 @@ pub fn typecheck_modules( module_index.clone(), source_indices.clone(), intern_table.clone(), + allocator.clone(), ); let typed = tc_result.typed.clone(); let tc_diags = tc_result.diagnostics.clone(); + allocator = tc_result.allocator.clone(); { let __tco_0 = Rc::new( remaining diff --git a/src/v2/stage0/src/v2_compiler_infer_env.rs b/src/v2/stage0/src/v2_compiler_infer_env.rs index 65666ca3f31..a43a30470af 100644 --- a/src/v2/stage0/src/v2_compiler_infer_env.rs +++ b/src/v2/stage0/src/v2_compiler_infer_env.rs @@ -4,14 +4,15 @@ use crate::std_induction::RecursionShape::{DirectRecursion, ListRecursion, OptionalRecursion}; use crate::std_induction::SubValueRelation::{PreservedValue, SubValueUnknown}; pub use crate::std_induction::{InductiveField, RecursionShape, SubValueRelation}; +pub use crate::std_types::SourceSpan; use crate::v2_rt; use crate::v2_rt::Witness; use crate::v2_rt::Witness::{Holds, Violates}; pub use crate::v2_std_core::{ - authored_name_at, empty_intern_table, intern, intern_find, intern_str, merge_intern_tables, - source_text_at, + authored_name_at, empty_intern_table, error_type, intern, intern_find, intern_str, + merge_intern_tables, source_text_at, }; -pub use crate::v2_std_core::{InternTable, NewlineIndex, Node}; +pub use crate::v2_std_core::{BindingId, InternTable, NewlineIndex, Node}; use crate::NonEmptyBTreeSet; use crate::NonEmptyVec; use std::collections::BTreeSet; @@ -21,6 +22,9 @@ use std::rc::Rc; #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct TypeEnv { pub bindings: Rc>>, + pub carrier_bindings: Rc>>, + pub decl_registry: Rc>>, + pub duplicate_decl_ids: Rc>, pub recursive_types: Rc>, pub recursive_type_set: Rc>, pub inductive_fields: Rc>>>>, @@ -35,6 +39,91 @@ pub struct TypeBinding { pub provenance: Rc, } +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct TypeDeclBinding { + pub binding_id: BindingId, + pub authority: Rc, + pub binding_key: i64, + pub decl_arity: i64, + pub name: String, + pub provenance: Rc, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct TypeDeclAuthority { + pub module_name: String, + pub decl_name: String, + pub decl_span: Rc, +} + +#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct BindingIdAllocator { + pub next_id: i64, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct BindingIdAllocResult { + pub binding_id: BindingId, + pub allocator: BindingIdAllocator, +} + +pub fn empty_binding_id_allocator() -> BindingIdAllocator { + BindingIdAllocator { next_id: 1 } +} + +pub fn alloc_binding_id(allocator: BindingIdAllocator) -> Rc { + Rc::new(BindingIdAllocResult { + binding_id: BindingId::mint(allocator.next_id.clone()), + allocator: BindingIdAllocator { + next_id: (allocator.next_id.clone() + 1), + }, + }) +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct DeclRegistryMergeState { + pub decl_registry: Rc>>, + pub duplicate_decl_ids: Rc>, +} + +pub fn merge_decl_registry_state( + state: Rc, + incoming: Rc>>, +) -> Rc { + Rc::new(v2_rt::map_keys(&incoming)).iter().cloned().fold( + state, + |acc: Rc, binding_id: BindingId| match v2_rt::map_get( + &incoming, + binding_id.clone(), + ) { + Some(binding) => match v2_rt::map_get(&acc.decl_registry.clone(), binding_id.clone()) { + Some(existing) => { + if (existing.authority.clone() == binding.authority.clone()) { + acc.clone() + } else { + Rc::new(DeclRegistryMergeState { + decl_registry: acc.decl_registry.clone(), + duplicate_decl_ids: v2_rt::rc_list_push( + acc.duplicate_decl_ids.clone(), + binding_id.clone(), + ), + }) + } + } + None => Rc::new(DeclRegistryMergeState { + decl_registry: v2_rt::rc_map_insert( + acc.decl_registry.clone(), + binding_id.clone(), + binding.clone(), + ), + duplicate_decl_ids: acc.duplicate_decl_ids.clone(), + }), + }, + None => acc.clone(), + }, + ) +} + pub fn is_recursive_type(env: Rc, ident: i64) -> bool { match v2_rt::map_get(&env.recursive_type_set.clone(), ident) { Some(_) => true, @@ -63,14 +152,109 @@ pub fn lookup_type_by_name(env: Rc, name: String) -> Option> { } } +pub fn lookup_decl_arity_for(env: Rc, node: Rc) -> Option { + match node.binding_id.clone() { + Some(binding_id) => match v2_rt::map_get(&env.decl_registry.clone(), binding_id.clone()) { + Some(decl) => Some(decl.decl_arity.clone()), + None => None, + }, + None => { + let node_name = authored_name(env.clone(), node.clone()); + let by_ident = match node.ident.clone() { + Some(id) => Rc::new(v2_rt::map_values(&env.decl_registry.clone())) + .iter() + .cloned() + .fold(None, |acc: _, decl: Rc| { + match acc.clone() { + Some(_) => acc.clone(), + None => { + if (decl.binding_key.clone() == id.clone()) { + Some(decl.decl_arity.clone()) + } else { + None + } + } + } + }), + None => None, + }; + match by_ident.clone() { + Some(_) => by_ident.clone(), + None => Rc::new(v2_rt::map_values(&env.decl_registry.clone())) + .iter() + .cloned() + .fold( + None, + |acc: Option, decl: Rc| match acc.clone() { + Some(_) => acc.clone(), + None => { + if (decl.name.clone().as_str() == node_name.clone().as_str()) { + Some(decl.decl_arity.clone()) + } else { + None + } + } + }, + ), + } + } + } +} + +pub fn lookup_carrier_type_for(env: Rc, node: Rc) -> Option> { + match node.binding_id.clone() { + Some(binding_id) => match v2_rt::map_get(&env.carrier_bindings.clone(), binding_id.clone()) + { + Some(binding) => Some(binding.resolved.clone()), + None => None, + }, + None => None, + } +} + +pub fn node_has_binding_id(n: Rc, binding_id: BindingId) -> bool { + match n.binding_id.clone() { + Some(actual) => (actual.clone() == binding_id), + None => false, + } +} + +pub fn lookup_binding_id_type_for(env: Rc, node: Rc) -> Option> { + match node.binding_id.clone() { + Some(binding_id) => match v2_rt::map_get(&env.decl_registry.clone(), binding_id.clone()) { + Some(decl) => match lookup_type(env.clone(), decl.binding_key.clone()) { + Some(resolved) => { + if node_has_binding_id(resolved.clone(), binding_id.clone()) { + Some(resolved.clone()) + } else { + match lookup_carrier_type_for(env.clone(), node.clone()) { + Some(carrier) => Some(carrier.clone()), + None => Some(error_type()), + } + } + } + None => lookup_carrier_type_for(env.clone(), node.clone()), + }, + None => lookup_carrier_type_for(env.clone(), node.clone()), + }, + None => None, + } +} + pub fn authored_name(env: Rc, node: Rc) -> String { authored_name_at(env.source_indices.clone(), node) } pub fn lookup_type_for(env: Rc, node: Rc) -> Option> { - match node.ident.clone() { - Some(id) => lookup_type(env.clone(), id.clone()), - None => lookup_type_by_name(env.clone(), authored_name(env.clone(), node.clone())), + match node.binding_id.clone() { + Some(_) => lookup_binding_id_type_for(env.clone(), node.clone()), + None => match node.ident.clone() { + Some(id) => match lookup_type(env.clone(), id.clone()) { + Some(resolved) => Some(resolved.clone()), + None => lookup_type_by_name(env.clone(), authored_name(env.clone(), node.clone())), + }, + None => lookup_type_by_name(env.clone(), authored_name(env.clone(), node.clone())), + }, } } @@ -219,6 +403,28 @@ pub fn merge_envs(envs: Rc>>) -> Rc { v2_rt::rc_map_merge(acc, env.bindings.clone()) }, ); + let merged_carrier_bindings = envs.clone().iter().cloned().fold( + v2_rt::rc_empty_map::>(), + |acc: Rc>>, env: Rc| { + v2_rt::rc_map_merge(acc, env.carrier_bindings.clone()) + }, + ); + let merged_decl_state = envs.clone().iter().cloned().fold( + Rc::new(DeclRegistryMergeState { + decl_registry: v2_rt::rc_empty_map::>(), + duplicate_decl_ids: Rc::new(vec![]), + }), + |acc: Rc, env: Rc| { + let with_prior_duplicates = Rc::new(DeclRegistryMergeState { + decl_registry: acc.decl_registry.clone(), + duplicate_decl_ids: v2_rt::concat( + acc.duplicate_decl_ids.clone(), + env.duplicate_decl_ids.clone(), + ), + }); + merge_decl_registry_state(with_prior_duplicates.clone(), env.decl_registry.clone()) + }, + ); let merged_recursive = envs .clone() .iter() @@ -250,6 +456,9 @@ pub fn merge_envs(envs: Rc>>) -> Rc { }; Rc::new(TypeEnv { bindings: merged_bindings, + carrier_bindings: merged_carrier_bindings, + decl_registry: merged_decl_state.decl_registry.clone(), + duplicate_decl_ids: merged_decl_state.duplicate_decl_ids.clone(), recursive_types: merged_recursive, recursive_type_set: merged_recursive_set, inductive_fields: merged_inductive_fields, diff --git a/src/v2/stage0/src/v2_compiler_infer_method.rs b/src/v2/stage0/src/v2_compiler_infer_method.rs index 66b758f5afe..25258c24c8a 100644 --- a/src/v2/stage0/src/v2_compiler_infer_method.rs +++ b/src/v2/stage0/src/v2_compiler_infer_method.rs @@ -40,6 +40,7 @@ pub fn type_variable_node(id: String) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } diff --git a/src/v2/stage0/src/v2_compiler_infer_patterns.rs b/src/v2/stage0/src/v2_compiler_infer_patterns.rs index 31aa950394e..c20db5d4053 100644 --- a/src/v2/stage0/src/v2_compiler_infer_patterns.rs +++ b/src/v2/stage0/src/v2_compiler_infer_patterns.rs @@ -97,6 +97,7 @@ pub fn synthesize_optional_present_variant(scrut: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let present_node = Rc::new(Node { name: "Present".to_string(), @@ -117,6 +118,7 @@ pub fn synthesize_optional_present_variant(scrut: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); present_node } @@ -147,6 +149,7 @@ pub fn synthesize_witness_holds_variant(scrut: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); Rc::new(Node { name: "Holds".to_string(), @@ -167,6 +170,7 @@ pub fn synthesize_witness_holds_variant(scrut: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -192,6 +196,7 @@ pub fn synthesize_witness_violates_variant(scrut: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let diagnostic_field = Rc::new(Node { name: "diagnostic".to_string(), @@ -214,6 +219,7 @@ pub fn synthesize_witness_violates_variant(scrut: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); Rc::new(Node { name: "Violates".to_string(), @@ -234,6 +240,7 @@ pub fn synthesize_witness_violates_variant(scrut: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } diff --git a/src/v2/stage0/src/v2_compiler_infer_resolve.rs b/src/v2/stage0/src/v2_compiler_infer_resolve.rs index 924fa9db204..f3c71e9b426 100644 --- a/src/v2/stage0/src/v2_compiler_infer_resolve.rs +++ b/src/v2/stage0/src/v2_compiler_infer_resolve.rs @@ -8,11 +8,12 @@ pub use crate::std_types::container_param_name; pub use crate::std_types::SourceSpan; pub use crate::v2_compiler_infer_env::{ authored_name, is_recursive_type, is_recursive_type_by_name, is_recursive_type_for, - lookup_type, lookup_type_by_name, lookup_type_for, + lookup_decl_arity_for, lookup_type, lookup_type_by_name, lookup_type_for, }; pub use crate::v2_compiler_infer_env::{TypeBinding, TypeEnv}; pub use crate::v2_compiler_infer_types::{ - child_type_node, is_declared_container_alias_spelling, node_is_keyed_collection, resolved_type, + child_type_node, is_declared_container_alias_spelling, node_is_bare_type_ref, + node_is_keyed_collection, resolved_type, }; use crate::v2_rt; use crate::v2_rt::Witness; @@ -39,9 +40,9 @@ pub use crate::v2_std_core::{ make_expr_node, make_field_init_node, make_field_node, make_interp_part_node, make_named_expr_node, make_param_node, make_resolved_param_node, make_resource_use_node, make_text_part_node, make_transport_node, map_children, no_span, node_name_span, - param_node_default_value, param_node_name_at, param_node_type_expr, resource_use_name_at, - resource_use_resource, string_type, transport_request_body, unit_type, - with_optional_cardinality, with_required_cardinality, + node_with_preserved_binding_id, param_node_default_value, param_node_name_at, + param_node_type_expr, resource_use_name_at, resource_use_resource, string_type, + transport_request_body, unit_type, with_optional_cardinality, with_required_cardinality, }; pub use crate::v2_std_core::{ Cardinality, CompilerDiagnostic, Connective, ErrorNode, ExprData, ExprErrorKind, InferredNode, @@ -60,27 +61,8 @@ pub fn is_type_variable(inferred: Rc) -> bool { } } -pub fn with_authored_identity(identity: Rc, structural: Rc) -> Rc { - Rc::new(Node { - name: structural.name.clone(), - ident: structural.ident.clone(), - span: structural.span.clone(), - ident_span: identity.ident_span.clone(), - children: structural.children.clone(), - connective: structural.connective.clone(), - params: structural.params.clone(), - inferred: structural.inferred.clone(), - return_cardinality: structural.return_cardinality.clone(), - uses: structural.uses.clone(), - body: structural.body.clone(), - transport: structural.transport.clone(), - properties: structural.properties.clone(), - type_annotation: structural.type_annotation.clone(), - is_self_recursive: structural.is_self_recursive.clone(), - has_non_tail_self_call: structural.has_non_tail_self_call.clone(), - match_pattern: structural.match_pattern.clone(), - expr_data: structural.expr_data.clone(), - }) +pub fn with_preserved_binding_id(identity: Rc, structural: Rc) -> Rc { + node_with_preserved_binding_id(identity, structural) } pub fn preserve_nominal_brand_on_resolve( @@ -89,85 +71,142 @@ pub fn preserve_nominal_brand_on_resolve( brand_name: String, source_indices: Rc>>, ) -> Rc { - if (((brand_name.clone().as_str() != "".to_string().as_str()) - && (brand_name.clone().as_str() - != authored_name_at(source_indices, structural.clone()).as_str())) + if (((identity.binding_id.clone() != None) + && (brand_name.clone().as_str() != "".to_string().as_str())) && !is_declared_container_alias_spelling(brand_name.clone())) { - with_authored_identity(identity, structural.clone()) + with_preserved_binding_id(identity.clone(), structural) } else { - structural.clone() + structural } } -pub fn peel_nominal_alias_identity(n: Rc, env: Rc, module_name: String) -> Rc { +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct AliasPeelResult { + pub node: Rc, + pub diagnostics: Rc>>, +} + +pub fn peel_nominal_alias_identity_result( + n: Rc, + env: Rc, + module_name: String, +) -> Rc { { let source_indices = env.source_indices.clone(); let brand = authored_name_at(source_indices.clone(), n.clone()); - match lookup_type_for(env.clone(), n.clone()) { - Some(resolved) => { - let structural = if (((resolved.connective.clone() == Connective::NoConnective) - && ((resolved.children.clone().len() as i64) == 0)) - && (resolved.inferred.clone() != None)) - { - match resolved.inferred.clone().as_deref().cloned() { - Some(InferredNode::Resolved { node: target, .. }) => resolve_node_bounded( - target.clone(), - env.clone(), - module_name.clone(), - 0, - ) - .resolved - .clone(), - _ => resolve_node_bounded( - resolved.clone(), - env.clone(), - module_name.clone(), - 0, - ) - .resolved - .clone(), - } - } else { - resolve_node_bounded(resolved.clone(), env.clone(), module_name.clone(), 0) - .resolved - .clone() - }; - if (((brand.clone().as_str() != "".to_string().as_str()) - && (brand.clone().as_str() - != authored_name_at(source_indices.clone(), structural.clone()).as_str())) - && !is_declared_container_alias_spelling(brand.clone())) - { - with_authored_identity(n.clone(), structural.clone()) - } else { - if (((resolved.connective.clone() == Connective::NoConnective) + if (is_declared_container_alias_spelling(brand.clone()) + && ((n.children.clone().len() as i64) > 0)) + { + Rc::new(AliasPeelResult { + node: n.clone(), + diagnostics: Rc::new(vec![]), + }) + } else { + match lookup_type_for(env.clone(), n.clone()) { + Some(resolved) => { + let structural_result = if (((resolved.connective.clone() + == Connective::NoConnective) && ((resolved.children.clone().len() as i64) == 0)) && (resolved.inferred.clone() != None)) { match resolved.inferred.clone().as_deref().cloned() { Some(InferredNode::Resolved { node: target, .. }) => { - let target_resolved = resolve_node_bounded( + resolve_alias_target( target.clone(), env.clone(), module_name.clone(), 0, ) - .resolved - .clone(); - with_authored_identity(n.clone(), target_resolved) } - _ => resolved.clone(), + _ => resolve_node_bounded( + resolved.clone(), + env.clone(), + module_name.clone(), + 0, + ), + } + } else { + resolve_node_bounded(resolved.clone(), env.clone(), module_name.clone(), 0) + }; + let structural = structural_result.resolved.clone(); + if ((((resolved.binding_id.clone() != None) + && (brand.clone().as_str() != "".to_string().as_str())) + && (brand.clone().as_str() + != authored_name_at(source_indices.clone(), structural.clone()) + .as_str())) + && !is_declared_container_alias_spelling(brand.clone())) + { + { + let branded = match resolved.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: target, .. }) => { + if node_is_bare_type_ref(target.clone()) { + structural.clone() + } else { + with_preserved_binding_id( + resolved.clone(), + structural.clone(), + ) + } + } + _ => { + with_preserved_binding_id(resolved.clone(), structural.clone()) + } + }; + Rc::new(AliasPeelResult { + node: branded, + diagnostics: structural_result.diagnostics.clone(), + }) } } else { - resolved.clone() + if (((resolved.connective.clone() == Connective::NoConnective) + && ((resolved.children.clone().len() as i64) == 0)) + && (resolved.inferred.clone() != None)) + { + match resolved.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: target, .. }) => { + let target_result = resolve_alias_target( + target.clone(), + env.clone(), + module_name.clone(), + 0, + ); + Rc::new(AliasPeelResult { + node: target_result.resolved.clone(), + diagnostics: v2_rt::concat( + structural_result.diagnostics.clone(), + target_result.diagnostics.clone(), + ), + }) + } + _ => Rc::new(AliasPeelResult { + node: resolved.clone(), + diagnostics: structural_result.diagnostics.clone(), + }), + } + } else { + Rc::new(AliasPeelResult { + node: resolved.clone(), + diagnostics: structural_result.diagnostics.clone(), + }) + } } } + None => Rc::new(AliasPeelResult { + node: n.clone(), + diagnostics: Rc::new(vec![]), + }), } - None => n.clone(), } } } +pub fn peel_nominal_alias_identity(n: Rc, env: Rc, module_name: String) -> Rc { + peel_nominal_alias_identity_result(n, env, module_name) + .node + .clone() +} + #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct NodeResolveResult { pub resolved: Rc, @@ -244,23 +283,32 @@ pub fn is_user_generic_use_site(n: Rc, env: Rc) -> bool { if has_structure { false } else { - match lookup_type_for(env.clone(), n.clone()) { - Some(decl) => { - if ((decl.params.clone().len() as i64) > 0) { + match lookup_decl_arity_for(env.clone(), n.clone()) { + Some(arity) => { + if (arity.clone() > 0) { if is_container_type(authored_name(env.clone(), n.clone())) { false } else { - if (decl.inferred.clone() != None) { - true - } else { - true - } + true } } else { false } } - None => false, + None => match lookup_type_for(env.clone(), n.clone()) { + Some(decl) => { + if ((decl.params.clone().len() as i64) > 0) { + if is_container_type(authored_name(env.clone(), n.clone())) { + false + } else { + true + } + } else { + false + } + } + None => false, + }, } } } @@ -309,6 +357,8 @@ pub fn substitute_type_slots( }); Rc::new(Node { name: child.name.clone(), + ident: child.ident.clone(), + binding_id: child.binding_id.clone(), span: child.span.clone(), ident_span: child.ident_span.clone(), children: substituted_args.clone(), @@ -327,7 +377,6 @@ pub fn substitute_type_slots( .clone(), match_pattern: child.match_pattern.clone(), expr_data: child.expr_data.clone(), - ident: None, }) } } else { @@ -357,6 +406,8 @@ pub fn substitute_type_slots( }; Rc::new(Node { name: n.name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: new_children, @@ -373,7 +424,6 @@ pub fn substitute_type_slots( has_non_tail_self_call: n.has_non_tail_self_call.clone(), match_pattern: n.match_pattern.clone(), expr_data: n.expr_data.clone(), - ident: None, }) } } @@ -408,25 +458,95 @@ pub fn classify_alias(target: Rc) -> AliasKind { } pub fn resolve_alias_target( - target: Rc, - env: Rc, - module_name: String, - depth: i64, -) -> Rc { - match classify_alias(target.clone()) { - AliasKind::AliasParameterized => { - resolve_node_bounded(target.clone(), env.clone(), module_name, (depth + 1)) - .resolved - .clone() + mut target: Rc, + mut env: Rc, + mut module_name: String, + mut depth: i64, +) -> Rc { + loop { + if (depth.clone() > 100) { + return Rc::new(NodeResolveResult { + resolved: target.clone(), + diagnostics: Rc::new(vec![make_error_node( + Rc::new(CompilerDiagnostic::InternalError { + message: v2_rt::concat( + v2_rt::concat( + "internal: alias resolution exceeded depth 100 for '".to_string(), + authored_name(env.clone(), target.clone()), + ), + "'".to_string(), + ), + span: target.span.clone(), + }), + module_name.clone(), + )]), + }); + } + match classify_alias(target.clone()) { + AliasKind::AliasParameterized => { + break resolve_node_bounded( + target.clone(), + env.clone(), + module_name.clone(), + (depth.clone() + 1), + ); + } + AliasKind::AliasLeaf => match lookup_type_for(env.clone(), target.clone()) { + Some(env_target) => { + if (((env_target.connective.clone() == Connective::NoConnective) + && ((env_target.children.clone().len() as i64) == 0)) + && (env_target.inferred.clone() != None)) + { + match env_target.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { + node: next_target, .. + }) => { + if (node_is_bare_type_ref(next_target.clone()) + && (authored_name(env.clone(), next_target.clone()).as_str() + == authored_name(env.clone(), env_target.clone()).as_str())) + { + break Rc::new(NodeResolveResult { + resolved: env_target.clone(), + diagnostics: Rc::new(vec![]), + }); + } else { + { + let __tco_0 = next_target.clone(); + let __tco_1 = (depth + 1); + target = __tco_0; + depth = __tco_1; + continue; + } + } + } + _ => { + break Rc::new(NodeResolveResult { + resolved: env_target.clone(), + diagnostics: Rc::new(vec![]), + }); + } + } + } else { + break Rc::new(NodeResolveResult { + resolved: env_target.clone(), + diagnostics: Rc::new(vec![]), + }); + } + } + None => { + break Rc::new(NodeResolveResult { + resolved: target.clone(), + diagnostics: Rc::new(vec![]), + }); + } + }, + AliasKind::AliasPassthrough => { + break Rc::new(NodeResolveResult { + resolved: target.clone(), + diagnostics: Rc::new(vec![]), + }); + } } - AliasKind::AliasLeaf => match lookup_type_by_name( - env.clone(), - authored_name_at(env.source_indices.clone(), target.clone()), - ) { - Some(env_target) => env_target.clone(), - None => target.clone(), - }, - AliasKind::AliasPassthrough => target.clone(), } } @@ -478,6 +598,7 @@ pub fn resolve_nominal_alias_rhs( resolved: Rc::new(Node { name: n.name.clone(), ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: resolved_args, @@ -530,7 +651,62 @@ pub fn resolve_node_bounded( }); } let has_structure = (n.connective.clone() != Connective::NoConnective); - if has_structure { + let env = if ((has_structure.clone() && (n.transport.clone() == None)) + && ((n.params.clone().len() as i64) > 0)) + { + n.params + .clone() + .iter() + .cloned() + .fold(env.clone(), |e: Rc, p: Rc| { + let tp_name = generic_param_name_at(p.clone(), e.source_indices.clone()); + let tp_intern = intern(e.intern_table.clone(), tp_name.clone()); + Rc::new(TypeEnv { + bindings: v2_rt::rc_map_insert( + e.bindings.clone(), + tp_intern.id.clone(), + Rc::new(TypeBinding { + name: tp_name.clone(), + resolved: Rc::new(Node { + name: tp_name.clone(), + span: kernel_span(tp_name.clone()), + ident_span: Some(kernel_span(tp_name.clone())), + children: Rc::new(vec![]), + connective: Connective::NoConnective, + params: Rc::new(vec![]), + inferred: Some(Rc::new(InferredNode::TypeVariable { + id: tp_name.clone(), + })), + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + transport: None, + properties: Rc::new(vec![]), + type_annotation: None, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }), + provenance: Rc::new(SubValueRelation::SubValueUnknown), + }), + ), + carrier_bindings: e.carrier_bindings.clone(), + decl_registry: e.decl_registry.clone(), + duplicate_decl_ids: e.duplicate_decl_ids.clone(), + recursive_types: e.recursive_types.clone(), + recursive_type_set: e.recursive_type_set.clone(), + inductive_fields: e.inductive_fields.clone(), + source_indices: e.source_indices.clone(), + intern_table: tp_intern.table.clone(), + }) + }) + } else { + env.clone() + }; + if has_structure.clone() { { let is_product = (n.connective.clone() == Connective::Conj); if is_product { @@ -548,6 +724,8 @@ pub fn resolve_node_bounded( Rc::new(NodeResolveResult { resolved: Rc::new(Node { name: n.name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: Rc::new(vec![base_resolved]), @@ -564,7 +742,6 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: base_diags, }) @@ -580,10 +757,68 @@ pub fn resolve_node_bounded( let mut __result = Vec::new(); for child in n.children.clone().iter().cloned() { __result.push(if (child.inferred.clone() == None) { - Rc::new(NodeResolveResult { - resolved: child.clone(), - diagnostics: Rc::new(vec![]), - }) + if ((child.children.clone().len() as i64) > 0) { + { + let authored_type = + field_node_type_expr(child.clone()); + let rt_result = resolve_node_bounded( + authored_type.clone(), + env.clone(), + module_name.clone(), + (depth.clone() + 1), + ); + let rt_resolved = rt_result.resolved.clone(); + let rt_diags = rt_result.diagnostics.clone(); + let resolved_children = + match field_node_default_value(child.clone()) { + Some(dv) => Rc::new(vec![ + rt_resolved.clone(), + dv.clone(), + ]), + None => Rc::new(vec![rt_resolved.clone()]), + }; + Rc::new(NodeResolveResult { + resolved: Rc::new(Node { + name: child.name.clone(), + ident: child.ident.clone(), + binding_id: child.binding_id.clone(), + span: child.span.clone(), + ident_span: child.ident_span.clone(), + children: resolved_children.clone(), + connective: child.connective.clone(), + params: child.params.clone(), + inferred: Some(Rc::new( + InferredNode::Resolved { + node: rt_resolved.clone(), + }, + )), + return_cardinality: child + .return_cardinality + .clone(), + uses: child.uses.clone(), + body: child.body.clone(), + transport: child.transport.clone(), + properties: v2_rt::concat( + child.properties.clone(), + rt_resolved.properties.clone(), + ), + type_annotation: child + .type_annotation + .clone(), + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + }), + diagnostics: rt_diags.clone(), + }) + } + } else { + Rc::new(NodeResolveResult { + resolved: child.clone(), + diagnostics: Rc::new(vec![]), + }) + } } else { { let child_rt = resolved_type(child.clone()); @@ -595,12 +830,22 @@ pub fn resolve_node_bounded( ); let rt_resolved = rt_result.resolved.clone(); let rt_diags = rt_result.diagnostics.clone(); + let resolved_children = + match field_node_default_value(child.clone()) { + Some(dv) => Rc::new(vec![ + rt_resolved.clone(), + dv.clone(), + ]), + None => Rc::new(vec![rt_resolved.clone()]), + }; Rc::new(NodeResolveResult { resolved: Rc::new(Node { name: child.name.clone(), + ident: child.ident.clone(), + binding_id: child.binding_id.clone(), span: child.span.clone(), ident_span: child.ident_span.clone(), - children: child.children.clone(), + children: resolved_children.clone(), connective: child.connective.clone(), params: child.params.clone(), inferred: Some(Rc::new( @@ -623,7 +868,6 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: rt_diags.clone(), }) @@ -649,9 +893,11 @@ pub fn resolve_node_bounded( Rc::new(NodeResolveResult { resolved: Rc::new(Node { name: n.name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), - children: resolved_children, + children: resolved_children.clone(), connective: n.connective.clone(), params: n.params.clone(), inferred: n.inferred.clone(), @@ -665,7 +911,6 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: all_diags, }) @@ -697,65 +942,25 @@ pub fn resolve_node_bounded( let mut __result = Vec::new(); for variant_child in n.children.clone().iter().cloned() { __result.push({ - let field_results = Rc::new({ - let mut __result = Vec::new(); - for field_child in - variant_child.children.clone().iter().cloned() + let field_results = Rc::new({ let mut __result = Vec::new(); for field_child in variant_child.children.clone().iter().cloned() { __result.push(if (field_child.inferred.clone() == None) { + if ((field_child.children.clone().len() as i64) > 0) { { - __result.push( - if (field_child.inferred.clone() == None) { - Rc::new(NodeResolveResult { - resolved: field_child.clone(), - diagnostics: Rc::new(vec![]), - }) - } else { - { - let field_rt = resolved_type( - field_child.clone(), - ); - let is_self_ref = ((authored_name( - env.clone(), - field_rt.clone(), - ) - .as_str() - == authored_name( - env.clone(), - n.clone(), - ) - .as_str()) - && ((field_rt - .children - .clone() - .len() - as i64) - > 0)); - let rt_result = if is_self_ref - .clone() - { - Rc::new(NodeResolveResult { - resolved: field_rt.clone(), - diagnostics: Rc::new( - vec![], - ), - }) - } else { - resolve_node_bounded( - field_rt.clone(), - env.clone(), - module_name.clone(), - (depth.clone() + 1), - ) - }; - let rt_resolved = - rt_result.resolved.clone(); - let rt_diags = - rt_result.diagnostics.clone(); - Rc::new(NodeResolveResult { + let authored_type = field_node_type_expr(field_child.clone()); +let rt_result = resolve_node_bounded(authored_type.clone(), env.clone(), module_name.clone(), (depth.clone() + 1)); +let rt_resolved = rt_result.resolved.clone(); +let rt_diags = rt_result.diagnostics.clone(); +let resolved_children = match field_node_default_value(field_child.clone()) { + Some(dv) => Rc::new(vec![rt_resolved.clone(), dv.clone()]), + None => Rc::new(vec![rt_resolved.clone()]), +}; +Rc::new(NodeResolveResult { resolved: Rc::new(Node { name: field_child.name.clone(), + ident: field_child.ident.clone(), + binding_id: field_child.binding_id.clone(), span: field_child.span.clone(), ident_span: field_child.ident_span.clone(), - children: field_child.children.clone(), + children: resolved_children.clone(), connective: field_child.connective.clone(), params: field_child.params.clone(), inferred: Some(Rc::new(InferredNode::Resolved { @@ -771,60 +976,89 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: rt_diags.clone(), }) - } - }, - ); - } - __result - }); - let resolved_fields = Rc::new({ - let mut __result = Vec::new(); - for fr in field_results.clone().iter().cloned() { - __result.push(fr.resolved.clone()); - } - __result - }); - let field_diags = Rc::new({ - let mut __result = Vec::new(); - for fr in field_results.clone().iter().cloned() { - __result.extend( - (*fr.diagnostics.clone()).iter().cloned(), - ); - } - __result - }); - Rc::new(NodeResolveResult { - resolved: Rc::new(Node { - name: variant_child.name.clone(), - span: variant_child.span.clone(), - ident_span: variant_child.ident_span.clone(), - children: resolved_fields.clone(), - connective: variant_child.connective.clone(), - params: variant_child.params.clone(), - inferred: variant_child.inferred.clone(), - return_cardinality: variant_child - .return_cardinality - .clone(), - uses: variant_child.uses.clone(), - body: variant_child.body.clone(), - transport: variant_child.transport.clone(), - properties: variant_child.properties.clone(), - type_annotation: variant_child - .type_annotation - .clone(), - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, - }), - diagnostics: field_diags.clone(), - }) - }); +} + } else { + Rc::new(NodeResolveResult { + resolved: field_child.clone(), + diagnostics: Rc::new(vec![]), +}) + } + } else { + { + let field_rt = resolved_type(field_child.clone()); +let is_self_ref = ((authored_name(env.clone(), field_rt.clone()).as_str() == authored_name(env.clone(), n.clone()).as_str()) && ((field_rt.children.clone().len() as i64) > 0)); +let rt_result = if is_self_ref.clone() { + Rc::new(NodeResolveResult { + resolved: field_rt.clone(), + diagnostics: Rc::new(vec![]), +}) + } else { + resolve_node_bounded(field_rt.clone(), env.clone(), module_name.clone(), (depth.clone() + 1)) + }; +let rt_resolved = rt_result.resolved.clone(); +let rt_diags = rt_result.diagnostics.clone(); +let resolved_children = match field_node_default_value(field_child.clone()) { + Some(dv) => Rc::new(vec![rt_resolved.clone(), dv.clone()]), + None => Rc::new(vec![rt_resolved.clone()]), +}; +Rc::new(NodeResolveResult { + resolved: Rc::new(Node { + name: field_child.name.clone(), + ident: field_child.ident.clone(), + binding_id: field_child.binding_id.clone(), + span: field_child.span.clone(), + ident_span: field_child.ident_span.clone(), + children: resolved_children.clone(), + connective: field_child.connective.clone(), + params: field_child.params.clone(), + inferred: Some(Rc::new(InferredNode::Resolved { + node: rt_resolved.clone(), +})), + return_cardinality: field_child.return_cardinality.clone(), + uses: field_child.uses.clone(), + body: field_child.body.clone(), + transport: field_child.transport.clone(), + properties: v2_rt::concat(field_child.properties.clone(), rt_resolved.properties.clone()), + type_annotation: field_child.type_annotation.clone(), + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), +}), + diagnostics: rt_diags.clone(), +}) +} + }); } __result }); +let resolved_fields = Rc::new({ let mut __result = Vec::new(); for fr in field_results.clone().iter().cloned() { __result.push(fr.resolved.clone()); } __result }); +let field_diags = Rc::new({ let mut __result = Vec::new(); for fr in field_results.clone().iter().cloned() { __result.extend((*fr.diagnostics.clone()).iter().cloned()); } __result }); +Rc::new(NodeResolveResult { + resolved: Rc::new(Node { + name: variant_child.name.clone(), + ident: variant_child.ident.clone(), + binding_id: variant_child.binding_id.clone(), + span: variant_child.span.clone(), + ident_span: variant_child.ident_span.clone(), + children: resolved_fields.clone(), + connective: variant_child.connective.clone(), + params: variant_child.params.clone(), + inferred: variant_child.inferred.clone(), + return_cardinality: variant_child.return_cardinality.clone(), + uses: variant_child.uses.clone(), + body: variant_child.body.clone(), + transport: variant_child.transport.clone(), + properties: variant_child.properties.clone(), + type_annotation: variant_child.type_annotation.clone(), + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), +}), + diagnostics: field_diags.clone(), +}) +}); } __result }); @@ -845,6 +1079,8 @@ pub fn resolve_node_bounded( Rc::new(NodeResolveResult { resolved: Rc::new(Node { name: n.name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: resolved_variants, @@ -861,7 +1097,6 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: all_diags, }) @@ -880,7 +1115,10 @@ pub fn resolve_node_bounded( Some(d) => d.clone(), None => n.clone(), }; - let expected_arity = (decl.params.clone().len() as i64); + let expected_arity = match lookup_decl_arity_for(env.clone(), n.clone()) { + Some(arity) => arity.clone(), + None => (decl.params.clone().len() as i64), + }; let actual_arity = (n.children.clone().len() as i64); let arity_diags = if (expected_arity.clone() != actual_arity.clone()) { Rc::new(vec![make_error_node( @@ -1005,6 +1243,8 @@ pub fn resolve_node_bounded( is_recursive_type_by_name(env.clone(), type_name.clone()); let expanded_node = Rc::new(Node { name: type_name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: target_result.resolved.clone().children.clone(), @@ -1021,10 +1261,11 @@ pub fn resolve_node_bounded( has_non_tail_self_call: n.has_non_tail_self_call.clone(), match_pattern: n.match_pattern.clone(), expr_data: n.expr_data.clone(), - ident: None, }); let resolved_node = Rc::new(Node { name: type_name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: resolved_args.clone(), @@ -1043,7 +1284,6 @@ pub fn resolve_node_bounded( has_non_tail_self_call: n.has_non_tail_self_call.clone(), match_pattern: n.match_pattern.clone(), expr_data: n.expr_data.clone(), - ident: None, }); Rc::new(NodeResolveResult { resolved: resolved_node, @@ -1071,6 +1311,8 @@ pub fn resolve_node_bounded( is_recursive_type_by_name(env.clone(), type_name.clone()); let expanded_node = Rc::new(Node { name: type_name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: substituted_children, @@ -1087,11 +1329,12 @@ pub fn resolve_node_bounded( has_non_tail_self_call: n.has_non_tail_self_call.clone(), match_pattern: n.match_pattern.clone(), expr_data: n.expr_data.clone(), - ident: None, }); let result = Rc::new(NodeResolveResult { resolved: Rc::new(Node { name: type_name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: resolved_args.clone(), @@ -1110,7 +1353,6 @@ pub fn resolve_node_bounded( has_non_tail_self_call: n.has_non_tail_self_call.clone(), match_pattern: n.match_pattern.clone(), expr_data: n.expr_data.clone(), - ident: None, }), diagnostics: v2_rt::concat(arity_diags, arg_diags), }); @@ -1168,6 +1410,8 @@ pub fn resolve_node_bounded( }; let resolved_key_child = Rc::new(Node { name: key_param_name, + ident: key_child_node.ident.clone(), + binding_id: key_child_node.binding_id.clone(), span: key_child_node.span.clone(), ident_span: key_child_node.ident_span.clone(), children: Rc::new(vec![]), @@ -1186,10 +1430,11 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }); let resolved_val_child = Rc::new(Node { name: val_param_name, + ident: val_child_node.ident.clone(), + binding_id: val_child_node.binding_id.clone(), span: val_child_node.span.clone(), ident_span: val_child_node.ident_span.clone(), children: Rc::new(vec![]), @@ -1208,11 +1453,12 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }); Rc::new(NodeResolveResult { resolved: Rc::new(Node { name: type_name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: Rc::new(vec![resolved_key_child, resolved_val_child]), @@ -1229,7 +1475,6 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: v2_rt::concat(key_diags, val_diags), }) @@ -1262,6 +1507,8 @@ pub fn resolve_node_bounded( }; let resolved_child = Rc::new(Node { name: el_param_name, + ident: child_node.ident.clone(), + binding_id: child_node.binding_id.clone(), span: child_node.span.clone(), ident_span: child_node.ident_span.clone(), children: Rc::new(vec![]), @@ -1280,11 +1527,12 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }); Rc::new(NodeResolveResult { resolved: Rc::new(Node { name: type_name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: Rc::new(vec![resolved_child]), @@ -1301,7 +1549,6 @@ pub fn resolve_node_bounded( has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: el_diags, }) @@ -1334,7 +1581,15 @@ pub fn resolve_node_bounded( Some(InferredNode::Resolved { node: target, .. - }) => target.clone(), + }) => match lookup_type_for( + env.clone(), + target.clone(), + ) { + Some(target_resolved) => { + target_resolved.clone() + } + None => target.clone(), + }, _ => resolved.clone(), } } else { @@ -1347,8 +1602,15 @@ pub fn resolve_node_bounded( } else { structurally_resolved }; + let branded_resolved = + preserve_nominal_brand_on_resolve( + resolved.clone(), + final_resolved, + authored_name(env.clone(), n.clone()), + env.source_indices.clone(), + ); Rc::new(NodeResolveResult { - resolved: final_resolved, + resolved: branded_resolved, diagnostics: Rc::new(vec![]), }) } @@ -1424,19 +1686,26 @@ pub fn missing_generic_args_diagnostics( { { let type_name = authored_name(env.clone(), n.clone()); - let decl = match lookup_type_for(env.clone(), n.clone()) { - Some(d) => d.clone(), - None => n.clone(), + let expected = match lookup_decl_arity_for(env.clone(), n.clone()) { + Some(arity) => arity.clone(), + None => match lookup_type_for(env.clone(), n.clone()) { + Some(decl) => (decl.params.clone().len() as i64), + None => (n.params.clone().len() as i64), + }, }; - Rc::new(vec![make_error_node( - Rc::new(CompilerDiagnostic::ArityMismatch { - name: type_name, - expected: (decl.params.clone().len() as i64), - got: 0, - span: n.span.clone(), - }), - module_name, - )]) + if (expected.clone() > 0) { + Rc::new(vec![make_error_node( + Rc::new(CompilerDiagnostic::ArityMismatch { + name: type_name, + expected: expected.clone(), + got: 0, + span: n.span.clone(), + }), + module_name, + )]) + } else { + Rc::new(vec![]) + } } } else { Rc::new(vec![]) @@ -1496,6 +1765,7 @@ pub fn resolve_optional_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), diagnostics: Rc::new(vec![]), }), @@ -1554,6 +1824,8 @@ pub fn resolve_param(param: Rc, env: Rc, module_name: String) -> let rendered_type = if ((authored_type.children.clone().len() as i64) > 0) { Rc::new(Node { name: authored_type.name.clone(), + ident: authored_type.ident.clone(), + binding_id: authored_type.binding_id.clone(), span: authored_type.span.clone(), ident_span: authored_type.ident_span.clone(), children: type_resolved.children.clone(), @@ -1572,7 +1844,6 @@ pub fn resolve_param(param: Rc, env: Rc, module_name: String) -> has_non_tail_self_call: authored_type.has_non_tail_self_call.clone(), match_pattern: authored_type.match_pattern.clone(), expr_data: authored_type.expr_data.clone(), - ident: None, }) } else { type_resolved.clone() @@ -2875,43 +3146,51 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) let env = tp_names.clone().iter().cloned().fold( env.clone(), |e: Rc, tp_name: String| { - Rc::new(TypeEnv { - bindings: v2_rt::rc_map_insert( - e.bindings.clone(), - intern(e.intern_table.clone(), tp_name.clone()).id.clone(), - Rc::new(TypeBinding { - name: tp_name.clone(), - resolved: Rc::new(Node { + let e = Rc::try_unwrap(e).unwrap_or_else(|rc| (*rc).clone()); + { + let tp_intern = intern(e.intern_table, tp_name.clone()); + Rc::new(TypeEnv { + bindings: v2_rt::rc_map_insert( + e.bindings, + tp_intern.id.clone(), + Rc::new(TypeBinding { name: tp_name.clone(), - span: kernel_span(tp_name.clone()), - ident_span: Some(kernel_span(tp_name.clone())), - children: Rc::new(vec![]), - connective: Connective::NoConnective, - params: Rc::new(vec![]), - inferred: Some(Rc::new(InferredNode::TypeVariable { - id: tp_name.clone(), - })), - return_cardinality: Cardinality::Required, - uses: Rc::new(vec![]), - body: None, - transport: None, - properties: Rc::new(vec![]), - type_annotation: None, - is_self_recursive: false, - has_non_tail_self_call: false, - match_pattern: None, - expr_data: Rc::new(ExprData::NoExprData), - ident: None, + resolved: Rc::new(Node { + name: tp_name.clone(), + span: kernel_span(tp_name.clone()), + ident_span: Some(kernel_span(tp_name.clone())), + children: Rc::new(vec![]), + connective: Connective::NoConnective, + params: Rc::new(vec![]), + inferred: Some(Rc::new(InferredNode::TypeVariable { + id: tp_name.clone(), + })), + return_cardinality: Cardinality::Required, + uses: Rc::new(vec![]), + body: None, + transport: None, + properties: Rc::new(vec![]), + type_annotation: None, + is_self_recursive: false, + has_non_tail_self_call: false, + match_pattern: None, + expr_data: Rc::new(ExprData::NoExprData), + ident: None, + binding_id: None, + }), + provenance: Rc::new(SubValueRelation::SubValueUnknown), }), - provenance: Rc::new(SubValueRelation::SubValueUnknown), - }), - ), - recursive_types: e.recursive_types.clone(), - recursive_type_set: e.recursive_type_set.clone(), - inductive_fields: e.inductive_fields.clone(), - source_indices: e.source_indices.clone(), - intern_table: e.intern_table.clone(), - }) + ), + carrier_bindings: e.carrier_bindings, + decl_registry: e.decl_registry, + duplicate_decl_ids: e.duplicate_decl_ids, + recursive_types: e.recursive_types, + recursive_type_set: e.recursive_type_set, + inductive_fields: e.inductive_fields, + source_indices: e.source_indices, + intern_table: tp_intern.table.clone(), + }) + } }, ); let param_results = Rc::new({ @@ -3082,12 +3361,18 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) module_name.clone(), ), ); + let resolved_children = match field_node_default_value(child.clone()) { + Some(dv) => Rc::new(vec![tr.resolved.clone(), dv.clone()]), + None => Rc::new(vec![tr.resolved.clone()]), + }; Rc::new(ItemResult { item: Rc::new(Node { name: child.name.clone(), + ident: child.ident.clone(), + binding_id: child.binding_id.clone(), span: child.span.clone(), ident_span: child.ident_span.clone(), - children: child.children.clone(), + children: resolved_children.clone(), connective: child.connective.clone(), params: child.params.clone(), inferred: child.inferred.clone(), @@ -3104,7 +3389,6 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: type_diags.clone(), }) @@ -3136,12 +3420,21 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) module_name.clone(), ), ); + let resolved_children = + match field_node_default_value(field.clone()) { + Some(dv) => { + Rc::new(vec![tr.resolved.clone(), dv.clone()]) + } + None => Rc::new(vec![tr.resolved.clone()]), + }; Rc::new(ItemResult { item: Rc::new(Node { name: field.name.clone(), + ident: field.ident.clone(), + binding_id: field.binding_id.clone(), span: field.span.clone(), ident_span: field.ident_span.clone(), - children: field.children.clone(), + children: resolved_children.clone(), connective: field.connective.clone(), params: field.params.clone(), inferred: field.inferred.clone(), @@ -3160,7 +3453,6 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: type_diags.clone(), }) @@ -3185,6 +3477,8 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) Rc::new(ItemResult { item: Rc::new(Node { name: variant.name.clone(), + ident: variant.ident.clone(), + binding_id: variant.binding_id.clone(), span: variant.span.clone(), ident_span: variant.ident_span.clone(), children: resolved_fields.clone(), @@ -3201,7 +3495,6 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: field_diags.clone(), }) @@ -3240,9 +3533,11 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) Rc::new(ItemResult { item: Rc::new(Node { name: item.name.clone(), + ident: item.ident.clone(), + binding_id: item.binding_id.clone(), span: item.span.clone(), ident_span: item.ident_span.clone(), - children: resolved_children, + children: resolved_children.clone(), params: resolved_params, inferred: resolved_ret, return_cardinality: item.return_cardinality.clone(), @@ -3256,7 +3551,6 @@ pub fn resolve_item_types(item: Rc, env: Rc, module_name: String) has_non_tail_self_call: false, match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), - ident: None, }), diagnostics: v2_rt::concat( v2_rt::concat( diff --git a/src/v2/stage0/src/v2_compiler_infer_service.rs b/src/v2/stage0/src/v2_compiler_infer_service.rs index 48f310ee365..4e360246d1a 100644 --- a/src/v2/stage0/src/v2_compiler_infer_service.rs +++ b/src/v2/stage0/src/v2_compiler_infer_service.rs @@ -374,6 +374,7 @@ pub fn check_service_method_call_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, })); } __result @@ -392,6 +393,7 @@ pub fn check_service_method_call_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), op_params: op.params.clone(), })) diff --git a/src/v2/stage0/src/v2_compiler_infer_types.rs b/src/v2/stage0/src/v2_compiler_infer_types.rs index 811e66b806f..0e9b6516334 100644 --- a/src/v2/stage0/src/v2_compiler_infer_types.rs +++ b/src/v2/stage0/src/v2_compiler_infer_types.rs @@ -79,6 +79,7 @@ pub fn type_variable_node(id: String) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -97,6 +98,50 @@ pub fn child_type_node(ch: Rc) -> Rc { } } +pub fn node_is_bare_type_ref(n: Rc) -> bool { + (((n.connective.clone() == Connective::NoConnective) + && ((n.children.clone().len() as i64) == 0)) + && ((n.params.clone().len() as i64) == 0)) +} + +pub fn node_bare_alias_target_name( + n: Rc, + source_indices: Rc>>, +) -> Option { + if node_is_bare_type_ref(n.clone()) { + match n.inferred.clone().as_deref().cloned() { + Some(InferredNode::Resolved { node: target, .. }) => { + if node_is_bare_type_ref(target.clone()) { + Some(authored_name_at(source_indices, target.clone())) + } else { + None + } + } + _ => None, + } + } else { + None + } +} + +pub fn nodes_are_transparent_bare_alias_pair( + left: Rc, + right: Rc, + source_indices: Rc>>, +) -> bool { + { + let left_name = authored_name_at(source_indices.clone(), left.clone()); + let right_name = authored_name_at(source_indices.clone(), right.clone()); + match node_bare_alias_target_name(left.clone(), source_indices.clone()) { + Some(left_target) => (left_target.clone().as_str() == right_name.as_str()), + None => match node_bare_alias_target_name(right.clone(), source_indices.clone()) { + Some(right_target) => (right_target.clone().as_str() == left_name.as_str()), + None => false, + }, + } + } +} + pub fn child_type_at(n: Rc, index: i64) -> Option> { match n.children.clone().get(index as usize).cloned() { Some(ch) => Some(child_type_node(ch.clone())), @@ -164,6 +209,8 @@ pub fn structural_carrier_template_name( canonical_template_name( Rc::new(Node { name: n.name.clone(), + ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: Some(kernel_span(n.name.clone())), children: n.children.clone(), @@ -180,7 +227,6 @@ pub fn structural_carrier_template_name( has_non_tail_self_call: n.has_non_tail_self_call.clone(), match_pattern: n.match_pattern.clone(), expr_data: n.expr_data.clone(), - ident: None, }), source_indices, ) @@ -189,6 +235,43 @@ pub fn structural_carrier_template_name( } } +pub fn free_monoid_coproduct_element( + n: Rc, + source_indices: Rc>>, +) -> Option> { + if ((n.connective.clone() == Connective::Disj) + && (canonical_template_name(n.clone(), source_indices.clone()).as_str() + == "FreeMonoid".to_string().as_str())) + { + { + let cons_variant = + find_child_named(n.clone(), "Cons".to_string(), source_indices.clone()); + match cons_variant { + Some(cons) => { + let head_by_name = match find_child_named( + cons.clone(), + "head".to_string(), + source_indices.clone(), + ) { + Some(head_field) => Some(child_type_node(head_field.clone())), + None => None, + }; + match head_by_name.clone() { + Some(_) => head_by_name.clone(), + None => match cons.children.clone().first().cloned() { + Some(first_field) => Some(child_type_node(first_field.clone())), + None => None, + }, + } + } + None => None, + } + } + } else { + None + } +} + pub fn is_product_type(n: Rc) -> bool { (n.connective.clone() == Connective::Conj) } @@ -202,7 +285,10 @@ pub fn is_leaf_type(n: Rc) -> bool { } pub fn is_unit_like(n: Rc) -> bool { - ((n.connective.clone() == Connective::Conj) && ((n.children.clone().len() as i64) == 0)) + (((n.connective.clone() == Connective::Conj) && ((n.children.clone().len() as i64) == 0)) + || (((n.connective.clone() == Connective::NoConnective) + && ((n.children.clone().len() as i64) == 0)) + && (n.name.clone().as_str() == "Unit".to_string().as_str()))) } pub fn is_fully_resolved( @@ -276,6 +362,7 @@ pub fn bare_map_node() -> Option> { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), Rc::new(Node { name: val_id.clone(), @@ -298,6 +385,7 @@ pub fn bare_map_node() -> Option> { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), ]), connective: Connective::NoConnective, @@ -314,6 +402,7 @@ pub fn bare_map_node() -> Option> { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, })), None => None, }, @@ -348,6 +437,7 @@ pub fn bare_set_node() -> Option> { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, })]), connective: Connective::NoConnective, params: Rc::new(vec![]), @@ -363,6 +453,7 @@ pub fn bare_set_node() -> Option> { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, })), None => None, } @@ -409,6 +500,7 @@ pub fn missing_kernel_container_profile_type(kind_name: String) -> Rc { message: msg.clone(), }), ident: None, + binding_id: None, }) } } @@ -445,6 +537,7 @@ pub fn make_container_type(kind_name: String, element: Rc) -> Rc) -> Rc, value: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), Rc::new(Node { name: val_name.clone(), @@ -520,6 +615,7 @@ pub fn make_map_type(key: Rc, value: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), ]), connective: Connective::NoConnective, @@ -536,6 +632,7 @@ pub fn make_map_type(key: Rc, value: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), diagnostics: Rc::new(vec![]), }), @@ -575,6 +672,7 @@ pub fn make_callable_type(func_params: Rc>>, ret: Rc) -> Rc, second: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), Rc::new(Node { name: "second".to_string(), @@ -623,6 +722,7 @@ pub fn make_tuple_type(first: Rc, second: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), ]), connective: Connective::Conj, @@ -639,6 +739,7 @@ pub fn make_tuple_type(first: Rc, second: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -662,6 +763,7 @@ pub fn algebra_value_field(name: String, type_node: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -704,6 +806,7 @@ pub fn algebra_method_field( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -715,6 +818,8 @@ pub fn enrich_base_with_fields( ) -> Rc { Rc::new(Node { name: name, + ident: base.ident.clone(), + binding_id: base.binding_id.clone(), span: base.span.clone(), ident_span: base.ident_span.clone(), children: fields, @@ -731,7 +836,6 @@ pub fn enrich_base_with_fields( has_non_tail_self_call: base.has_non_tail_self_call.clone(), match_pattern: base.match_pattern.clone(), expr_data: base.expr_data.clone(), - ident: None, }) } @@ -1762,11 +1866,11 @@ pub fn node_type_shape( } pub fn node_type_compatible( - mut left: Rc, - mut right: Rc, - mut source_indices: Rc>>, + left: Rc, + right: Rc, + source_indices: Rc>>, ) -> bool { - loop { + stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || { let left_err = if (left.inferred.clone() != None) { is_compiler_error(left.inferred.clone().clone().unwrap()) } else { @@ -1792,145 +1896,344 @@ pub fn node_type_compatible( let right_is_unit = is_unit_like(right.clone()); let left_is_unit = is_unit_like(left.clone()); if (left_err || right_err) { - break true; + true } else { if (left_tv || right_tv) { - break true; + true } else { if (left_opt.clone() && right_is_unit) { - break true; + true } else { if (left_is_unit && right_opt.clone()) { - break true; + true } else { - let left_is_container = - node_is_element_collection(left.clone(), source_indices.clone()); - let right_is_container = - node_is_element_collection(right.clone(), source_indices.clone()); - if (left_is_container && right_is_container) { - if (canonical_template_name(left.clone(), source_indices.clone()) - .as_str() - != canonical_template_name(right.clone(), source_indices.clone()) + { + let left_is_container = + node_is_element_collection(left.clone(), source_indices.clone()); + let right_is_container = + node_is_element_collection(right.clone(), source_indices.clone()); + if (left_is_container.clone() && right_is_container.clone()) { + if (canonical_template_name(left.clone(), source_indices.clone()) + .as_str() + != canonical_template_name( + right.clone(), + source_indices.clone(), + ) .as_str()) - { - break false; - } else { - match left.children.clone().first().cloned() { - Some(left_ch) => { - match right.children.clone().first().cloned() { - Some(right_ch) => { - let left_el = child_type_node(left_ch.clone()); - let right_el = child_type_node(right_ch.clone()); - let left_el_is_unit = is_unit_like(left_el.clone()); - let right_el_is_unit = - is_unit_like(right_el.clone()); - if (left_el_is_unit || right_el_is_unit) { - break true; - } else { - { - let __tco_0 = left_el.clone(); - let __tco_1 = right_el.clone(); - left = __tco_0; - right = __tco_1; - continue; + { + false + } else { + match left.children.clone().first().cloned() { + Some(left_ch) => { + match right.children.clone().first().cloned() { + Some(right_ch) => { + let left_el = child_type_node(left_ch.clone()); + let right_el = + child_type_node(right_ch.clone()); + let left_el_is_unit = + is_unit_like(left_el.clone()); + let right_el_is_unit = + is_unit_like(right_el.clone()); + if (left_el_is_unit || right_el_is_unit) { + true + } else { + node_type_compatible( + left_el.clone(), + right_el.clone(), + source_indices.clone(), + ) } } - } - None => { - break true; + None => true, } } - } - None => { - break true; + None => true, } } - } - } else { - if (((((canonical_template_name( - left.clone(), - source_indices.clone(), - ) - .as_str() - == canonical_template_name( - right.clone(), - source_indices.clone(), - ) - .as_str()) - && (authored_name_at(source_indices.clone(), left.clone()) - .as_str() - != authored_name_at(source_indices.clone(), right.clone()) - .as_str())) - && ((left.children.clone().len() as i64) == 1)) - && ((right.children.clone().len() as i64) == 1)) - && (is_declared_container_alias_spelling(authored_name_at( - source_indices.clone(), + } else { + if ((free_monoid_coproduct_element( left.clone(), - )) || is_declared_container_alias_spelling(authored_name_at( source_indices.clone(), - right.clone(), - )))) - { - match left.children.clone().first().cloned() { - Some(left_ch) => { - match right.children.clone().first().cloned() { - Some(right_ch) => { + ) != None) + && (free_monoid_coproduct_element( + right.clone(), + source_indices.clone(), + ) != None)) + { + { + let left_el = free_monoid_coproduct_element( + left.clone(), + source_indices.clone(), + ) + .clone() + .unwrap(); + let right_el = free_monoid_coproduct_element( + right.clone(), + source_indices.clone(), + ) + .clone() + .unwrap(); + if (is_unit_like(left_el.clone()) + || is_unit_like(right_el.clone())) + { + true + } else { + node_type_compatible( + left_el.clone(), + right_el.clone(), + source_indices.clone(), + ) + } + } + } else { + if (left_is_container.clone() + && (free_monoid_coproduct_element( + right.clone(), + source_indices.clone(), + ) != None)) + { + match left.children.clone().first().cloned() { + Some(left_ch) => { let left_el = child_type_node(left_ch.clone()); - let right_el = child_type_node(right_ch.clone()); + let right_el = free_monoid_coproduct_element( + right.clone(), + source_indices.clone(), + ) + .clone() + .unwrap(); if (is_unit_like(left_el.clone()) || is_unit_like(right_el.clone())) { - break true; + true } else { - { - let __tco_0 = left_el.clone(); - let __tco_1 = right_el.clone(); - left = __tco_0; - right = __tco_1; - continue; - } + node_type_compatible( + left_el.clone(), + right_el.clone(), + source_indices.clone(), + ) } } - None => { - break true; - } + None => true, } - } - None => { - break true; - } - } - } else { - if (left_opt.clone() && right_opt.clone()) { - let left_inner = with_required_cardinality(left.clone()); - let right_inner = with_required_cardinality(right.clone()); - let left_inner_is_unit = is_unit_like(left_inner.clone()); - let right_inner_is_unit = is_unit_like(right_inner.clone()); - if (left_inner_is_unit || right_inner_is_unit) { - break true; } else { + if (right_is_container.clone() + && (free_monoid_coproduct_element( + left.clone(), + source_indices.clone(), + ) != None)) { - let __tco_0 = left_inner.clone(); - let __tco_1 = right_inner.clone(); - left = __tco_0; - right = __tco_1; - continue; - } - } - } else { - if (left_opt.clone() || right_opt.clone()) { - break false; - } else { - break (authored_name_at( - source_indices.clone(), - left.clone(), - ) - .as_str() - == authored_name_at( + match right.children.clone().first().cloned() { + Some(right_ch) => { + let left_el = free_monoid_coproduct_element( + left.clone(), + source_indices.clone(), + ) + .clone() + .unwrap(); + let right_el = + child_type_node(right_ch.clone()); + if (is_unit_like(left_el.clone()) + || is_unit_like(right_el.clone())) + { + true + } else { + node_type_compatible( + left_el.clone(), + right_el.clone(), + source_indices.clone(), + ) + } + } + None => true, + } + } else { + if (node_is_keyed_collection( + left.clone(), source_indices.clone(), + ) && node_is_keyed_collection( right.clone(), - ) - .as_str()); + source_indices.clone(), + )) { + if (authored_name_at( + source_indices.clone(), + left.clone(), + ) + .as_str() + != authored_name_at( + source_indices.clone(), + right.clone(), + ) + .as_str()) + { + false + } else { + if (((left.children.clone().len() as i64) != 2) + || ((right.children.clone().len() as i64) + != 2)) + { + false + } else { + match left.children.clone().first().cloned() { + Some(left_key_ch) => match right.children.clone().first().cloned() { + Some(right_key_ch) => match left.children.clone().get(1 as usize).cloned() { + Some(left_val_ch) => match right.children.clone().get(1 as usize).cloned() { + Some(right_val_ch) => (node_type_compatible(child_type_node(left_key_ch.clone()), child_type_node(right_key_ch.clone()), source_indices.clone()) && node_type_compatible(child_type_node(left_val_ch.clone()), child_type_node(right_val_ch.clone()), source_indices.clone())), + None => false, +}, + None => false, +}, + None => false, +}, + None => false, +} + } + } + } else { + if ((((canonical_template_name( + left.clone(), + source_indices.clone(), + ) + .as_str() + == canonical_template_name( + right.clone(), + source_indices.clone(), + ) + .as_str()) + && ((left.children.clone().len() as i64) + == 1)) + && ((right.children.clone().len() as i64) + == 1)) + && (is_declared_container_alias_spelling( + authored_name_at( + source_indices.clone(), + left.clone(), + ), + ) || is_declared_container_alias_spelling( + authored_name_at( + source_indices.clone(), + right.clone(), + ), + ))) + { + match left.children.clone().first().cloned() { + Some(left_ch) => match right + .children + .clone() + .first() + .cloned() + { + Some(right_ch) => { + let left_el = child_type_node( + left_ch.clone(), + ); + let right_el = child_type_node( + right_ch.clone(), + ); + if (is_unit_like(left_el.clone()) + || is_unit_like( + right_el.clone(), + )) + { + true + } else { + node_type_compatible( + left_el.clone(), + right_el.clone(), + source_indices.clone(), + ) + } + } + None => true, + }, + None => true, + } + } else { + if (left_opt.clone() && right_opt.clone()) { + { + let left_inner = + with_required_cardinality( + left.clone(), + ); + let right_inner = + with_required_cardinality( + right.clone(), + ); + let left_inner_is_unit = + is_unit_like(left_inner.clone()); + let right_inner_is_unit = + is_unit_like(right_inner.clone()); + if (left_inner_is_unit + || right_inner_is_unit) + { + true + } else { + node_type_compatible( + left_inner.clone(), + right_inner.clone(), + source_indices.clone(), + ) + } + } + } else { + if (left_opt.clone() || right_opt.clone()) { + false + } else { + if nodes_are_transparent_bare_alias_pair( + left.clone(), + right.clone(), + source_indices.clone(), + ) { + true + } else { + if (((left.binding_id.clone() + != None) + && (right.binding_id.clone() + != None)) + && (left.binding_id.clone() + == right + .binding_id + .clone())) + { + true + } else { + if ((authored_name_at( + source_indices.clone(), + left.clone(), + ) + .as_str() + == authored_name_at( + source_indices.clone(), + right.clone(), + ) + .as_str()) + && is_kernel_type( + authored_name_at( + source_indices + .clone(), + left.clone(), + ), + )) + { + true + } else { + match left.binding_id.clone() { + Some(left_binding_id) => match right.binding_id.clone() { + Some(right_binding_id) => (left_binding_id.clone() == right_binding_id.clone()), + None => false, +}, + None => match right.binding_id.clone() { + Some(_) => false, + None => (authored_name_at(source_indices.clone(), left.clone()).as_str() == authored_name_at(source_indices.clone(), right.clone()).as_str()), +}, +} + } + } + } + } + } + } + } + } } } } @@ -1939,7 +2242,7 @@ pub fn node_type_compatible( } } } - } + }) } pub fn prefer_specific_type( diff --git a/src/v2/stage0/src/v2_compiler_parse.rs b/src/v2/stage0/src/v2_compiler_parse.rs index 5986cef9480..827d87ba517 100644 --- a/src/v2/stage0/src/v2_compiler_parse.rs +++ b/src/v2/stage0/src/v2_compiler_parse.rs @@ -23,7 +23,7 @@ use crate::v2_rt; use crate::v2_rt::Witness; use crate::v2_rt::Witness::{Holds, Violates}; use crate::v2_std_core::Cardinality::{CardOptional, Required}; -use crate::v2_std_core::CompilerDiagnostic::ParseError; +use crate::v2_std_core::CompilerDiagnostic::{InternalError, ParseError}; use crate::v2_std_core::Connective::{Arrow, Conj, Disj, NoConnective}; use crate::v2_std_core::ExprData::{ ExprBinOp, ExprBlock, ExprCall, ExprCast, ExprFieldAccess, ExprForEach, ExprIf, ExprIndex, @@ -1758,7 +1758,7 @@ pub fn parser_helper_state_arg_expr( ) .iter() .cloned() - .fold(None, |acc: _, pair: (i64, Rc)| { + .fold(None, |acc: Option>, pair: (i64, Rc)| { if (acc.clone() != None) { acc.clone() } else { @@ -1893,6 +1893,7 @@ pub fn leaf_type_node(name: String, span: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -2149,6 +2150,7 @@ pub fn parse_module(tokens: Rc>>, ctx: Rc) -> Rc>>, ctx: Rc) -> Rc>>, ctx: Rc) -> Rc>>, ctx: Rc) -> Rc< match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); Rc::new(TypeResult { type_expr: te, @@ -4550,6 +4574,7 @@ pub fn parse_callable_type_expr( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); maybe_optional(ret.tokens.clone(), ret.ctx.clone(), te, start_span.clone()) } @@ -4661,6 +4686,7 @@ pub fn finish_type_expr_from_name( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); maybe_optional( r3.tokens.clone(), @@ -4826,6 +4852,7 @@ pub fn maybe_optional( match_pattern: te.match_pattern.clone(), expr_data: te.expr_data.clone(), ident: None, + binding_id: None, }); Rc::new(TypeResult { type_expr: ote, @@ -5094,6 +5121,7 @@ pub fn parse_fn_def(tokens: Rc>>, ctx: Rc) -> Rc>>, ctx: Rc) -> Rc>>, ctx: Rc) -> Rc match_pattern: r3.type_expr.clone().match_pattern.clone(), expr_data: r3.type_expr.clone().expr_data.clone(), ident: None, + binding_id: None, }); let ru = make_resource_use_node(name, res_node, start_span.clone(), r.span.clone()); Rc::new(ResUseResult { @@ -5965,6 +6006,7 @@ pub fn parse_service_def(tokens: Rc>>, ctx: Rc) -> R match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let r = expect( tokens.clone(), @@ -6009,6 +6051,7 @@ pub fn parse_service_after_kw( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let r_ns = expect_name(tokens.clone()); if has_err(r_ns.err.clone()) { @@ -6046,6 +6089,7 @@ pub fn parse_service_after_kw( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let r = expect(r.tokens.clone(), Rc::new(ExpectedToken::ExpectLBrace)); if has_err(r.err.clone()) { @@ -6121,6 +6165,7 @@ pub fn parse_service_after_kw( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); Rc::new(ItemResult { item: item, @@ -8694,6 +8739,7 @@ pub fn parse_resource_def(tokens: Rc>>, ctx: Rc) -> match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let r = expect( tokens.clone(), @@ -8738,6 +8784,7 @@ pub fn parse_resource_after_kw( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let r = expect_ident(tokens); if has_err(r.err.clone()) { @@ -8769,6 +8816,7 @@ pub fn parse_resource_after_kw( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let r = expect(r.tokens.clone(), Rc::new(ExpectedToken::ExpectLBrace)); if has_err(r.err.clone()) { @@ -8824,6 +8872,7 @@ pub fn parse_resource_after_kw( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); Rc::new(ItemResult { item: item, @@ -9441,6 +9490,7 @@ pub fn parse_data_def(tokens: Rc>>, ctx: Rc) -> Rc>>, ctx: Rc) -> Rc< match_pattern: None, expr_data: Rc::new(ExprData::ExprLet), ident: None, + binding_id: None, }); Rc::new(ExprResult { expr: node, @@ -10215,6 +10270,7 @@ pub fn parse_bare_assignment(tokens: Rc>>, ctx: Rc) match_pattern: node.match_pattern.clone(), expr_data: node.expr_data.clone(), ident: None, + binding_id: None, }); Rc::new(ExprResult { expr: node.clone(), diff --git a/src/v2/stage0/src/v2_std_core.rs b/src/v2/stage0/src/v2_std_core.rs index 36441bffb48..dd689368fd6 100644 --- a/src/v2/stage0/src/v2_std_core.rs +++ b/src/v2/stage0/src/v2_std_core.rs @@ -701,10 +701,22 @@ pub struct DeclaredFuncEnv { pub signatures: Rc>>, } +#[derive( + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize, +)] +pub struct BindingId(i64); + +impl BindingId { + pub(crate) fn mint(value: i64) -> Self { + BindingId(value) + } +} + #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct Node { pub name: String, pub ident: Option, + pub binding_id: Option, pub span: Rc, pub ident_span: Option>, pub children: Rc>>, @@ -738,6 +750,54 @@ pub fn node_name_span(n: Rc) -> Rc { } } +pub fn node_with_binding_id(n: Rc, binding_id: BindingId) -> Rc { + Rc::new(Node { + name: n.name.clone(), + ident: n.ident.clone(), + binding_id: Some(binding_id), + span: n.span.clone(), + ident_span: n.ident_span.clone(), + children: n.children.clone(), + connective: n.connective.clone(), + params: n.params.clone(), + inferred: n.inferred.clone(), + return_cardinality: n.return_cardinality.clone(), + uses: n.uses.clone(), + body: n.body.clone(), + transport: n.transport.clone(), + properties: n.properties.clone(), + type_annotation: n.type_annotation.clone(), + is_self_recursive: n.is_self_recursive.clone(), + has_non_tail_self_call: n.has_non_tail_self_call.clone(), + match_pattern: n.match_pattern.clone(), + expr_data: n.expr_data.clone(), + }) +} + +pub fn node_with_preserved_binding_id(identity: Rc, structural: Rc) -> Rc { + Rc::new(Node { + name: structural.name.clone(), + ident: structural.ident.clone(), + binding_id: identity.binding_id.clone(), + span: structural.span.clone(), + ident_span: structural.ident_span.clone(), + children: structural.children.clone(), + connective: structural.connective.clone(), + params: structural.params.clone(), + inferred: structural.inferred.clone(), + return_cardinality: structural.return_cardinality.clone(), + uses: structural.uses.clone(), + body: structural.body.clone(), + transport: structural.transport.clone(), + properties: structural.properties.clone(), + type_annotation: structural.type_annotation.clone(), + is_self_recursive: structural.is_self_recursive.clone(), + has_non_tail_self_call: structural.has_non_tail_self_call.clone(), + match_pattern: structural.match_pattern.clone(), + expr_data: structural.expr_data.clone(), + }) +} + pub fn make_expr_node( expr_data: Rc, children: Rc>>, @@ -763,6 +823,7 @@ pub fn make_expr_node( match_pattern: None, expr_data: expr_data, ident: None, + binding_id: None, }) } @@ -793,6 +854,7 @@ pub fn make_named_expr_node( match_pattern: None, expr_data: expr_data, ident: None, + binding_id: None, }) } @@ -826,6 +888,7 @@ pub fn make_expr_error_node( message: message.clone(), }), ident: None, + binding_id: None, }) } @@ -859,6 +922,7 @@ pub fn make_arg_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -893,6 +957,7 @@ pub fn make_arm_node( match_pattern: Some(pattern), expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -922,6 +987,7 @@ pub fn make_resource_use_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -968,6 +1034,7 @@ pub fn make_field_init_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -996,6 +1063,7 @@ pub fn make_field_binding_node( match_pattern: Some(binding), expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -1035,6 +1103,7 @@ pub fn make_text_part_node(text: String, span: Rc) -> Rc { value: Rc::new(LiteralValue::LitStr { value: text }), }), ident: None, + binding_id: None, }) } @@ -1058,6 +1127,7 @@ pub fn make_interp_part_node(expr: Rc, span: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -1092,6 +1162,7 @@ pub fn make_param_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -1130,6 +1201,7 @@ pub fn make_resolved_param_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -1283,6 +1355,7 @@ pub fn make_field_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }), make_span(0, 0), make_span(0, 0), @@ -1308,6 +1381,7 @@ pub fn make_field_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -1385,6 +1459,7 @@ pub fn make_variant_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -2035,6 +2110,7 @@ pub fn make_transport_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -2155,6 +2231,7 @@ pub fn shell_transport_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }); let zero_span = make_span(0, 0); let stdin_props = match stdin { @@ -2186,6 +2263,7 @@ pub fn shell_transport_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -2454,6 +2532,7 @@ pub fn map_children(node: Rc, transform: impl Fn(Rc) -> Rc + C Rc::new(Node { name: node.name.clone(), ident: node.ident.clone(), + binding_id: node.binding_id.clone(), span: node.span.clone(), ident_span: node.ident_span.clone(), children: Rc::new({ @@ -2959,6 +3038,7 @@ pub fn module_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -2990,6 +3070,7 @@ pub fn import_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, })) } else { None @@ -3013,6 +3094,7 @@ pub fn import_node( match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } } @@ -3062,6 +3144,7 @@ pub fn leaf_node_with_span(name: String, span: Rc) -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) } @@ -3098,6 +3181,7 @@ pub fn unit_type() -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) }; } @@ -3126,6 +3210,7 @@ pub fn bool_type() -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) }; } @@ -3154,6 +3239,7 @@ pub fn string_type() -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) }; } @@ -3182,6 +3268,7 @@ pub fn hash_type() -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) }; } @@ -3210,6 +3297,7 @@ pub fn int_type() -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) }; } @@ -3238,6 +3326,7 @@ pub fn float_type() -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) }; } @@ -3266,6 +3355,7 @@ pub fn none_type() -> Rc { match_pattern: None, expr_data: Rc::new(ExprData::NoExprData), ident: None, + binding_id: None, }) }; } @@ -3309,6 +3399,7 @@ pub fn error_type() -> Rc { message: "unresolved type".to_string(), }), ident: None, + binding_id: None, }) }; } @@ -3559,6 +3650,7 @@ pub fn with_optional_cardinality(n: Rc) -> Rc { Rc::new(Node { name: n.name.clone(), ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: n.children.clone(), @@ -3582,6 +3674,7 @@ pub fn with_required_cardinality(n: Rc) -> Rc { Rc::new(Node { name: n.name.clone(), ident: n.ident.clone(), + binding_id: n.binding_id.clone(), span: n.span.clone(), ident_span: n.ident_span.clone(), children: n.children.clone(), diff --git a/src/v2/tests/src/infer_semantics.rs b/src/v2/tests/src/infer_semantics.rs index 133f6480daa..910b751fa0f 100644 --- a/src/v2/tests/src/infer_semantics.rs +++ b/src/v2/tests/src/infer_semantics.rs @@ -11,7 +11,8 @@ use v2_compiler::v2_compiler_infer_patterns::{self, NodeLookupStatus}; use v2_compiler::v2_compiler_infer_resolve::resolve_node; use v2_compiler::v2_compiler_infer_sigs::ResolvedFuncEnv; use v2_compiler::v2_compiler_infer_types::{ - bare_map_node, is_fully_resolved, node_is_keyed_collection, node_type_compatible, resolved_type, + bare_map_node, is_fully_resolved, make_container_type, make_map_type, node_is_keyed_collection, + node_type_compatible, resolved_type, }; use v2_compiler::v2_compiler_parse; use v2_compiler::v2_std_core::NewlineIndex; @@ -39,11 +40,13 @@ fn container_node(kind_name: String, element: Rc) -> Rc { Rc::new(Node { name: kind_name.clone(), ident: None, + binding_id: None, span: sp.clone(), ident_span: default_ident_span(kind_name, sp.clone()), children: Rc::new(vec![Rc::new(Node { name: param_name.clone(), ident: None, + binding_id: None, span: sp.clone(), ident_span: default_ident_span(param_name, sp.clone()), children: Rc::new(vec![]), @@ -86,12 +89,14 @@ fn map_node(key: Rc, value: Rc) -> Rc { Rc::new(Node { name: "Map".to_string(), ident: None, + binding_id: None, span: sp.clone(), ident_span: Some(sp.clone()), children: Rc::new(vec![ Rc::new(Node { name: key_name, ident: None, + binding_id: None, span: sp.clone(), ident_span: Some(sp.clone()), children: Rc::new(vec![]), @@ -112,6 +117,7 @@ fn map_node(key: Rc, value: Rc) -> Rc { Rc::new(Node { name: val_name, ident: None, + binding_id: None, span: sp.clone(), ident_span: Some(sp.clone()), children: Rc::new(vec![]), @@ -161,6 +167,9 @@ fn unit_expr() -> Rc { fn empty_type_env() -> Rc { Rc::new(TypeEnv { bindings: Rc::new(std::collections::HashMap::new()), + carrier_bindings: Rc::new(std::collections::HashMap::new()), + decl_registry: Rc::new(std::collections::HashMap::new()), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: Rc::new(std::collections::HashMap::new()), inductive_fields: Rc::new(std::collections::HashMap::new()), @@ -176,6 +185,7 @@ fn empty_infer_scope() -> Rc { signatures: Rc::new(std::collections::HashMap::new()), }), locals: Rc::new(std::collections::HashMap::new()), + variant_collisions: Rc::new(std::collections::HashMap::new()), match_bound_names: Rc::new(std::collections::HashMap::new()), module_name: "test".to_string(), service_registry: Rc::new(std::collections::HashMap::new()), @@ -189,6 +199,7 @@ fn sum_node(name: &str, variants: Vec>, cardinality: Cardinality) -> Rc Rc::new(Node { name: name.to_string(), ident: None, + binding_id: None, span: sp.clone(), ident_span: default_ident_span(name.to_string(), sp), children: Rc::new(variants), @@ -277,6 +288,35 @@ type AccountId = Refined .expect("Refined type binding"); let string = lookup_type_by_name(module.type_env.clone(), "String".to_string()) .expect("String type binding"); + let user_binding_id = user_id + .binding_id + .expect("UserId must carry declaration binding_id"); + let account_binding_id = account_id + .binding_id + .expect("AccountId must carry declaration binding_id"); + + assert_ne!( + user_binding_id, account_binding_id, + "brand twins must differ on binding_id, not only spelling or ident_span" + ); + assert_eq!( + module + .type_env + .decl_registry + .get(&user_binding_id) + .expect("UserId binding id must be registered") + .name, + "UserId" + ); + assert_eq!( + module + .type_env + .decl_registry + .get(&account_binding_id) + .expect("AccountId binding id must be registered") + .name, + "AccountId" + ); assert_eq!( user_id, same_user_id, @@ -357,6 +397,108 @@ type AccountId = Refined ); } +#[test] +fn pd3_kernel_container_shells_are_structural_and_recurse_to_branded_elements() { + let source = r#" +module pd3.kernel_container_brand_relation + +type Refined { + base: T +} +type UserId = Refined +type AccountId = Refined +"#; + + let result = crate::helpers::compile_dag_resolved(source); + assert!( + result.diagnostics.is_empty(), + "kernel container brand probe should resolve cleanly, got: {:?}", + result + .diagnostics + .iter() + .map(|d| v2_compiler::v2_std_core::diagnostic_to_message(d.diagnostic.clone())) + .collect::>() + ); + let graph = result.graph.as_ref().expect("resolved graph"); + let module = graph + .modules + .iter() + .find(|m| { + v2_compiler::v2_std_core::authored_name_at( + result.source_indices.clone(), + m.module.clone(), + ) == "pd3.kernel_container_brand_relation" + }) + .expect("pd3.kernel_container_brand_relation module"); + + let user_id = + lookup_type_by_name(module.type_env.clone(), "UserId".to_string()).expect("UserId binding"); + let account_id = lookup_type_by_name(module.type_env.clone(), "AccountId".to_string()) + .expect("AccountId binding"); + assert_ne!( + user_id.binding_id, account_id.binding_id, + "brand twins must have distinct binding_id before entering kernel containers" + ); + + let list_user = make_container_type("List".to_string(), user_id.clone()) + .ty + .clone(); + let list_account = make_container_type("List".to_string(), account_id.clone()) + .ty + .clone(); + assert_eq!( + list_user.binding_id, None, + "kernel List shell must stay brand-free; element carries declaration identity" + ); + assert_eq!( + list_account.binding_id, None, + "kernel List shell must stay brand-free; element carries declaration identity" + ); + assert!( + !node_type_compatible( + list_user.clone(), + list_account, + result.source_indices.clone() + ), + "List vs List must reject by recursing to branded elements" + ); + assert!( + node_type_compatible(list_user.clone(), list_user, result.source_indices.clone()), + "same kernel List shell with same branded element must accept" + ); + + let map_user_key = make_map_type(user_id.clone(), leaf_node("String".to_string())) + .ty + .clone(); + let map_account_key = make_map_type(account_id.clone(), leaf_node("String".to_string())) + .ty + .clone(); + assert_eq!( + map_user_key.binding_id, None, + "kernel Map shell must stay brand-free; key/value children carry declaration identity" + ); + assert_eq!( + map_account_key.binding_id, None, + "kernel Map shell must stay brand-free; key/value children carry declaration identity" + ); + assert!( + !node_type_compatible( + map_user_key.clone(), + map_account_key, + result.source_indices.clone() + ), + "Map vs Map must reject by recursing to branded keys" + ); + assert!( + node_type_compatible( + map_user_key.clone(), + map_user_key, + result.source_indices.clone() + ), + "same kernel Map shell with same branded key/value must accept" + ); +} + #[test] fn pd3_direct_call_rejects_brand_twin_mismatch() { let source = r#" @@ -389,6 +531,32 @@ fn caller(uid: UserId) -> String { ); } +#[test] +fn pd3_direct_call_rejects_canonical_kernel_leaf_mismatch() { + let source = r#" +module pd3.kernel_leaf_call_reject + +fn take_secret(value: Secret) -> Int { + 0 +} + +fn caller(value: String) -> Int { + take_secret(value) +} +"#; + + let result = crate::helpers::compile_dag(source); + let has_type_mismatch = result + .diagnostics + .iter() + .any(|diag| matches!(&*diag.diagnostic, CompilerDiagnostic::TypeMismatch { .. })); + assert!( + has_type_mismatch, + "PD-3: direct call must reject String-for-Secret via canonical kernel type set, got: {:?}", + crate::helpers::diagnostic_messages(&result) + ); +} + #[test] fn pd3_direct_call_accepts_same_brand() { let source = r#" @@ -606,11 +774,13 @@ fn optional_pattern_lookup_prefers_optional_present_over_inner_present_variant() let inner_present = Rc::new(Node { name: "Present".to_string(), ident: None, + binding_id: None, span: sp.clone(), ident_span: default_ident_span("Present".to_string(), sp.clone()), children: Rc::new(vec![Rc::new(Node { name: "inner".to_string(), ident: None, + binding_id: None, span: sp.clone(), ident_span: default_ident_span("inner".to_string(), sp.clone()), children: Rc::new(vec![]), @@ -647,6 +817,7 @@ fn optional_pattern_lookup_prefers_optional_present_over_inner_present_variant() let optional_inner_sum = Rc::new(Node { name: "Inner".to_string(), ident: None, + binding_id: None, span: sp.clone(), ident_span: default_ident_span("Inner".to_string(), sp.clone()), children: Rc::new(vec![inner_present]), @@ -760,6 +931,9 @@ fn optional_match_exhaustiveness_reports_missing_absent() { Rc::new(vec![variant_arm("Present")]), Rc::new(TypeEnv { bindings: Rc::new(std::collections::HashMap::new()), + carrier_bindings: Rc::new(std::collections::HashMap::new()), + decl_registry: Rc::new(std::collections::HashMap::new()), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: Rc::new(std::collections::HashMap::new()), inductive_fields: Rc::new(std::collections::HashMap::new()), @@ -783,6 +957,9 @@ fn optional_match_exhaustiveness_rejects_some_and_none() { Rc::new(vec![variant_arm("Some"), variant_arm("None")]), Rc::new(TypeEnv { bindings: Rc::new(std::collections::HashMap::new()), + carrier_bindings: Rc::new(std::collections::HashMap::new()), + decl_registry: Rc::new(std::collections::HashMap::new()), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: Rc::new(std::collections::HashMap::new()), inductive_fields: Rc::new(std::collections::HashMap::new()), @@ -806,6 +983,9 @@ fn optional_match_exhaustiveness_accepts_present_and_absent() { Rc::new(vec![variant_arm("Present"), variant_arm("Absent")]), Rc::new(TypeEnv { bindings: Rc::new(std::collections::HashMap::new()), + carrier_bindings: Rc::new(std::collections::HashMap::new()), + decl_registry: Rc::new(std::collections::HashMap::new()), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: Rc::new(std::collections::HashMap::new()), inductive_fields: Rc::new(std::collections::HashMap::new()), @@ -828,6 +1008,7 @@ fn resolve_node_uses_node_name_for_lookup() { let node_ref = Rc::new(Node { name: "User".to_string(), ident: None, + binding_id: None, span: zero_span(), ident_span: Some(Rc::new(v2_compiler::v2_std_core::SourceSpan { file: "".to_string(), @@ -862,6 +1043,9 @@ fn resolve_node_uses_node_name_for_lookup() { provenance: Rc::new(SubValueRelation::SubValueUnknown), }), )])), + carrier_bindings: Rc::new(std::collections::HashMap::new()), + decl_registry: Rc::new(std::collections::HashMap::new()), + duplicate_decl_ids: Rc::new(vec![]), recursive_types: Rc::new(vec![]), recursive_type_set: Rc::new(std::collections::HashMap::new()), inductive_fields: Rc::new(std::collections::HashMap::new()), diff --git a/src/v2/tests/src/pd3_adversarial.rs b/src/v2/tests/src/pd3_adversarial.rs index 8cb6a43a5f8..b9383d8c60a 100644 --- a/src/v2/tests/src/pd3_adversarial.rs +++ b/src/v2/tests/src/pd3_adversarial.rs @@ -11,6 +11,8 @@ //! (3) over-reject UserId-for-UserId (same brand must pass) //! (4) suite regression (covered by running the full crate) +use v2_compiler::v2_compiler_artifact::RenderTarget; +use v2_compiler::v2_compiler_compile::SourceFile; use v2_compiler::v2_std_core::CompilerDiagnostic; fn has_type_mismatch(result: &v2_compiler::v2_compiler_compile::PipelineResult) -> bool { @@ -20,6 +22,21 @@ fn has_type_mismatch(result: &v2_compiler::v2_compiler_compile::PipelineResult) .any(|d| matches!(&*d.diagnostic, CompilerDiagnostic::TypeMismatch { .. })) } +fn compile_sources( + files: &[(&str, &str)], +) -> std::rc::Rc { + let sources = files + .iter() + .map(|(path, content)| { + std::rc::Rc::new(SourceFile { + path: (*path).to_string(), + content: (*content).to_string(), + }) + }) + .collect(); + v2_compiler::v2_compiler_compile::compile_sources(std::rc::Rc::new(sources), RenderTarget::Rust) +} + // ── (1) FALSE-ACCEPT brand-twin: harder variants than the basic positive ── // Twin in 2nd arg position — guards the enumerate/skip index pairing. @@ -78,6 +95,118 @@ fn caller(us: List) -> Int { ); } +// Twin record declarations over the same structural field must stay distinct. +#[test] +fn adv_record_twins_must_reject() { + let source = r#" +module pd3adv.record_twins + +type UserId { + value: String +} +type AccountId { + value: String +} + +fn take_account(id: AccountId) -> String { + id.value +} + +fn caller(uid: UserId) -> String { + take_account(uid) +} +"#; + let result = crate::helpers::compile_dag(source); + assert!( + has_type_mismatch(&result), + "PD-3 ADV: record twins must be rejected, got: {:?}", + crate::helpers::diagnostic_messages(&result) + ); +} + +// Same spelling in different modules must not coalesce through binding_key/name. +#[test] +fn adv_same_named_decls_in_different_modules_must_stay_distinct() { + let mod_a = r#" +module pd3adv.same_name.a + +type Id { + value: String +} + +fn accept(id: Id) -> String { + id.value +} + +fn same(id: Id) -> String { + accept(id) +} +"#; + let mod_b = r#" +module pd3adv.same_name.b + +type Id { + value: String +} + +fn accept(id: Id) -> String { + id.value +} + +fn same(id: Id) -> String { + accept(id) +} +"#; + let use_a_from_b = r#" +module pd3adv.same_name.use_a_from_b + +import pd3adv.same_name.a { accept } +import pd3adv.same_name.b { Id } + +fn caller(id: Id) -> String { + accept(id) +} +"#; + let use_b_from_a = r#" +module pd3adv.same_name.use_b_from_a + +import pd3adv.same_name.a { Id } +import pd3adv.same_name.b { accept } + +fn caller(id: Id) -> String { + accept(id) +} +"#; + + let same_a = compile_sources(&[("a.dag", mod_a)]); + crate::helpers::assert_no_diagnostics(&same_a); + + let same_b = compile_sources(&[("b.dag", mod_b)]); + crate::helpers::assert_no_diagnostics(&same_b); + + let reject_a_from_b = compile_sources(&[ + ("a.dag", mod_a), + ("b.dag", mod_b), + ("use_a_from_b.dag", use_a_from_b), + ]); + assert!( + has_type_mismatch(&reject_a_from_b), + "PD-3 ADV: same-named Id from module b must not satisfy module a's Id, got: {:?}", + crate::helpers::diagnostic_messages(&reject_a_from_b) + ); + + let reject_b_from_a = compile_sources(&[ + ("a.dag", mod_a), + ("b.dag", mod_b), + ("use_b_from_a.dag", use_b_from_a), + ]); + assert!( + has_type_mismatch(&reject_b_from_a), + "PD-3 ADV: same-named Id from module a must not satisfy module b's Id, got: {:?}", + crate::helpers::diagnostic_messages(&reject_b_from_a) + ); +} + // Twin where the value flows through a let-binding before the call. #[test] fn adv_brand_twin_via_let_must_reject() { @@ -145,6 +274,28 @@ fn caller(xs: FreeMonoid>) -> Int { crate::helpers::assert_no_diagnostics(&result); } +// Alias transparency must not hide a genuine element mismatch. +#[test] +fn adv_alias_with_element_mismatch_must_reject() { + let source = r#" +module pd3adv.alias_element_mismatch + +fn take_list(xs: List) -> Int { + 0 +} + +fn caller(xs: FreeMonoid) -> Int { + take_list(xs) +} +"#; + let result = crate::helpers::compile_dag(source); + assert!( + has_type_mismatch(&result), + "PD-3 ADV: List/FreeMonoid alias must still reject element mismatch, got: {:?}", + crate::helpers::diagnostic_messages(&result) + ); +} + // ── (3) OVER-REJECT same brand: UserId-for-UserId variants ── // Same brand in 2nd arg slot. @@ -210,3 +361,25 @@ fn caller(s: String) -> Int { let result = crate::helpers::compile_dag(source); crate::helpers::assert_no_diagnostics(&result); } + +// Plain unrelated types must still be rejected through the ordinary type gate. +#[test] +fn adv_plain_int_for_string_must_reject() { + let source = r#" +module pd3adv.plain_bad + +fn take_str(s: String) -> Int { + 0 +} + +fn caller(i: Int) -> Int { + take_str(i) +} +"#; + let result = crate::helpers::compile_dag(source); + assert!( + has_type_mismatch(&result), + "PD-3 ADV: plain Int for String must be rejected, got: {:?}", + crate::helpers::diagnostic_messages(&result) + ); +} diff --git a/src/v2/tests/src/pipeline.rs b/src/v2/tests/src/pipeline.rs index 92d21884474..790e4120309 100644 --- a/src/v2/tests/src/pipeline.rs +++ b/src/v2/tests/src/pipeline.rs @@ -1393,6 +1393,48 @@ fn sg8_variant_import_uses_defining_module_not_import_site_for_parent() { ); } +#[test] +fn sg8_variant_import_does_not_import_record_with_same_named_field() { + let files = &[ + ( + "def.dag", + "module sg8_variant_field_boundary\ntype E = SharedName | Other\ntype RecordWithSameField { SharedName: Int }\n", + ), + ( + "use_mod.dag", + "module sg8_variant_field_use\nimport sg8_variant_field_boundary { SharedName }\nfn ok() -> E { SharedName }\nfn bad(x: RecordWithSameField) -> Int { x.SharedName }\n", + ), + ]; + let result = compile_multi(files); + let msgs = diagnostic_messages(&result); + assert!( + msgs.iter().any(|m| m.contains("RecordWithSameField")), + "variant-only import must not import a record parent through a same-named field, got: {msgs:?}" + ); +} + +#[test] +fn sg8_variant_import_same_variant_from_two_parents_collides() { + let files = &[ + ("left.dag", "module sg8_left_enum\ntype LeftE = Shared | LeftOnly\n"), + ("right.dag", "module sg8_right_enum\ntype RightE = Shared | RightOnly\n"), + ( + "use_mod.dag", + "module sg8_variant_collision_use\nimport sg8_left_enum { Shared }\nimport sg8_right_enum { Shared }\nfn f() -> LeftE { Shared }\n", + ), + ]; + let result = compile_multi(files); + let msgs = diagnostic_messages(&result); + assert!( + msgs.iter().any(|m| { + m.contains("variant 'Shared' appears in both") + && m.contains("LeftE") + && m.contains("RightE") + }), + "variant-only imports with the same child name must fail closed, got: {msgs:?}" + ); +} + #[test] fn sg8_variant_import_not_suppressed_by_type_homonym_in_other_module() { let files = &[ diff --git a/src/v4/compiler/00_compile.dag b/src/v4/compiler/00_compile.dag index 1e7973d96d6..59abda3217c 100644 --- a/src/v4/compiler/00_compile.dag +++ b/src/v4/compiler/00_compile.dag @@ -15,9 +15,9 @@ import v4.compiler.name_resolve { ResolutionSubject, resolve_with_admission } -import v4.compiler.normalize { normalize } +import v4.compiler.normalize { normalize, NormalizedTree } import v4.compiler.parse { parse } -import v4.compiler.resolve { resolve } +import v4.compiler.resolve { resolve, ResolvedTree } import v4.compiler.tokenize { tokenize } import v4.compiler.target_carriers { TargetModel, TargetSource } import v4.extdeps.languages.dag { dag_language_model_wave1 } @@ -42,6 +42,8 @@ import v4.std.diagnostic { outcome_with_diagnostics } import v4.std.node { Edge, Node, NodeFold, Symbol, fold_node } +import v4.std.grammar { ParseTree } +import v4.std.target_model { TargetModelBundle } import v4.std.text { String } import v4.std.witness { Holds, Violates, Witness } @@ -52,6 +54,34 @@ type RuntimeTarget = Node type Source = String +fn source_to_string(source: Source) -> String { + source +} + +fn target_model_to_bundle(target: TargetModel) -> TargetModelBundle { + target +} + +fn core_node_to_node(source: CoreNode) -> Node { + source +} + +fn normalized_tree_to_node(tree: NormalizedTree) -> Node { + tree +} + +fn parse_tree_to_node(tree: ParseTree) -> Node { + tree +} + +fn node_to_core_node(tree: Node) -> CoreNode { + tree +} + +fn resolved_tree_to_core_node(tree: ResolvedTree) -> CoreNode { + tree +} + // 🟢 coproduct dissolution type CompileMode = TranslateTo { target: TargetModel } @@ -197,6 +227,13 @@ fn empty_lens_gate_witnesses() -> List { [] } +fn append_lens_gate_witnesses( + left: List, + right: List +) -> List { + list_append(left: left, right: right) +} + fn run_required_lens_gates( inferred: InferredTree, @@ -247,7 +284,7 @@ fn run_required_lens_gates_on_subtree( bind_outcome( o: child, f: fn(child_ws) { - outcome_accepted(value: list_append(left: ws, right: child_ws)) + outcome_accepted(value: append_lens_gate_witnesses(left: ws, right: child_ws)) } ) }) @@ -261,7 +298,7 @@ fn compile_inferred_translate( inferred: InferredTree, target: TargetModel ) -> Outcome { - emit(tree: inferred, target: target) + emit(tree: inferred, target: target_model_to_bundle(target: target)) } @@ -295,7 +332,7 @@ fn compile( mode: CompileMode ) -> Outcome { bind_outcome( - o: infer(tree: source), + o: infer(tree: core_node_to_node(source: source)), f: fn(inferred) { compile_inferred(inferred: inferred, mode: mode) } @@ -320,7 +357,7 @@ fn validate_then_compile( mode: CompileMode ) -> Outcome> { bind_outcome( - o: infer(tree: source), + o: infer(tree: core_node_to_node(source: source)), f: fn(inferred) { bind_outcome( o: run_required_lens_gates_on_subtree(inferred: inferred, lenses: always_required_lenses()), @@ -337,7 +374,7 @@ fn validate_then_compile( outcome_accepted( value: validated_from_compile_output( output: compile_out, - lens_witnesses: list_append( + lens_witnesses: append_lens_gate_witnesses( left: required_lens_witnesses, right: caller_lens_witnesses ) @@ -358,7 +395,7 @@ fn compile_ingest_staging(source: Source, target: TargetModel) -> Outcome Outcome Outcome Bool { WhitespaceChar => c == 32 || c == 9 || c == 10 || c == 13 DigitChar => - nat_gte(a: c, b: 48) && nat_lte(a: c, b: 57) + c >= 48 && c <= 57 HexDigitChar => - (nat_gte(a: c, b: 48) && nat_lte(a: c, b: 57)) || - (nat_gte(a: c, b: 65) && nat_lte(a: c, b: 70)) || - (nat_gte(a: c, b: 97) && nat_lte(a: c, b: 102)) + (c >= 48 && c <= 57) || + (c >= 65 && c <= 70) || + (c >= 97 && c <= 102) IdentStartChar => - (nat_gte(a: c, b: 65) && nat_lte(a: c, b: 90)) || - (nat_gte(a: c, b: 97) && nat_lte(a: c, b: 122)) || + (c >= 65 && c <= 90) || + (c >= 97 && c <= 122) || c == 95 IdentContinueChar => - (nat_gte(a: c, b: 65) && nat_lte(a: c, b: 90)) || - (nat_gte(a: c, b: 97) && nat_lte(a: c, b: 122)) || + (c >= 65 && c <= 90) || + (c >= 97 && c <= 122) || c == 95 || - (nat_gte(a: c, b: 48) && nat_lte(a: c, b: 57)) + (c >= 48 && c <= 57) StringTextChar => c != 34 && c != 10 LineCommentTextChar => diff --git a/src/v4/compiler/02_parse.dag b/src/v4/compiler/02_parse.dag index dd3e57ce7bf..a2909ee9db4 100644 --- a/src/v4/compiler/02_parse.dag +++ b/src/v4/compiler/02_parse.dag @@ -273,11 +273,11 @@ fn grammar_lookup_production(root: GrammarRoot, name: Symbol) -> Witness uses structural == on K; ParsePositionKey { position: Int, production: Symbol } is a valid composite key. -fn parse_table_lookup(table: ParseTable, key: ParsePositionKey) -> Witness { +fn parse_table_lookup(table: Map, key: ParsePositionKey) -> Witness { table.lookup(key) } -fn parse_table_insert(table: ParseTable, key: ParsePositionKey, value: ParseExprResult) -> ParseTable { +fn parse_table_insert(table: Map, key: ParsePositionKey, value: ParseExprResult) -> Map { map_insert(m: table, key: key, value: value) } @@ -480,7 +480,7 @@ fn parse_wrap_production_captured( } fn parse_nonterminal_from_table( - table: ParseTable, + table: Map, all_tokens: List, tokens: List, root: GrammarRoot, @@ -587,6 +587,16 @@ fn grammar_empty_corner_list() -> List { Empty } +fn symbol_list_snoc(xs: List, item: Symbol) -> List { + fold_list( + xs: [item], + empty: xs, + cons: fn(acc, current) { + list_snoc_item(xs: acc, item: current) + } + ) +} + fn expr_corner_fold_terminal(_: Symbol) -> GrammarExprCornerFold { GrammarExprCornerFold { corners: Empty, nullable: false } @@ -692,7 +702,7 @@ fn compute_left_corner_closure( if contains(xs: r, item: name, eq: fn(a, b) { a == b }) { r } else { - list_snoc_item(xs: r, item: name) + symbol_list_snoc(xs: r, item: name) } } ) @@ -876,7 +886,7 @@ fn parse_expr_run_walk( tokens: List, all_tokens: List, root: GrammarRoot, - table: ParseTable, + table: Map, prov: ParseProvenanceState ) -> ParseExprResult { match walk { @@ -1057,7 +1067,7 @@ fn parse_expr( tokens: List, all_tokens: List, root: GrammarRoot, - table: ParseTable, + table: Map, prov: ParseProvenanceState ) -> ParseExprResult { parse_expr_run_walk( @@ -1082,7 +1092,7 @@ fn parse_expr( type ParseTableBuildAcc { - table: ParseTable + table: Map prov: ParseProvenanceState } @@ -1159,7 +1169,7 @@ fn parse_table_fill_position( } -fn parse_table_empty() -> ParseTable { +fn parse_table_empty() -> Map { empty_map() } diff --git a/src/v4/compiler/03_name_resolve.dag b/src/v4/compiler/03_name_resolve.dag index f511d279ea6..6793ca0000b 100644 --- a/src/v4/compiler/03_name_resolve.dag +++ b/src/v4/compiler/03_name_resolve.dag @@ -81,6 +81,10 @@ type AdmittedSubject { subject_root: NormalizedTree } +fn normalized_tree_to_node(tree: NormalizedTree) -> Node { + tree +} + // 🟡 gated — feature:T-28-B-admission-state-outcome — internal fold state mirrors Outcome while carrying accepted namespace bindings plus origin facts for ambiguity checks; dissolve-on: generic Outcome fold/traverse can carry the accepted admission accumulator directly without losing the origin map. type AdmissionState @@ -557,7 +561,7 @@ fn resolve_with_admission( ) { Accepted { value: admitted, diagnostics: namespace_diag } => match resolve_with_namespace( - tree: admitted.subject_root, + tree: normalized_tree_to_node(tree: admitted.subject_root), namespace: admitted.namespace ) { Accepted { value: resolved, diagnostics: resolve_diag } => diff --git a/src/v4/compiler/03_normalize.dag b/src/v4/compiler/03_normalize.dag index 71ea4075b9c..5ddef66f371 100644 --- a/src/v4/compiler/03_normalize.dag +++ b/src/v4/compiler/03_normalize.dag @@ -6,7 +6,7 @@ module v4.compiler.normalize -import v4.std.algebra { list_snoc_item } +import v4.std.algebra { Empty, list_snoc_item } import v4.std.collection { Absent, Present, optional_absent, optional_present } import v4.std.grammar { ParseTree } @@ -25,6 +25,7 @@ import v4.std.node { Connective, Edge, Node, + NodeOccurrenceId, OccurrenceId, Symbol, TypeNode, @@ -209,7 +210,7 @@ fn normalize_node(n: Node) -> Outcome { } } -fn normalize(parse_tree: ParseTree) -> Outcome { +fn normalize(parse_tree: Node) -> Outcome { match normalize_node(n: parse_tree) { Rejected { diagnostics: r } => Rejected { diagnostics: r } Accepted { value: normalized, diagnostics: d } => diff --git a/src/v4/compiler/03_resolve.dag b/src/v4/compiler/03_resolve.dag index 33fa4a1a643..cdedf0fdadc 100644 --- a/src/v4/compiler/03_resolve.dag +++ b/src/v4/compiler/03_resolve.dag @@ -44,6 +44,7 @@ import v4.std.node { Edge, Node, NodeFold, + NodeOccurrenceId, OccurrenceId, Symbol, TypeNode, @@ -192,7 +193,7 @@ fn add_bind_atom_binder(n: Node, acc: Map) -> Map Namespace { +fn build_program_namespace(tree: Node, lm: DagLanguageModel) -> Namespace { Namespace { bindings: add_module_named_exports(root: tree, acc: empty_map()), canonical_symbols: dag_language_model_canonical_symbols(lm: lm) @@ -578,7 +579,7 @@ fn resolve_bind_node(n: Node, scope: Scope) -> Outcome { } -fn resolve(tree: NormalizedTree, lm: DagLanguageModel) -> Outcome { +fn resolve(tree: Node, lm: DagLanguageModel) -> Outcome { resolve_with_namespace( tree: tree, namespace: build_program_namespace(tree: tree, lm: lm) @@ -586,7 +587,7 @@ fn resolve(tree: NormalizedTree, lm: DagLanguageModel) -> Outcome } -fn resolve_with_namespace(tree: NormalizedTree, namespace: Namespace) -> Outcome { +fn resolve_with_namespace(tree: Node, namespace: Namespace) -> Outcome { if well_formed(n: tree) { resolve_node(n: tree, scope: scope_from_namespace(namespace: namespace)) } else { diff --git a/src/v4/compiler/04_infer.dag b/src/v4/compiler/04_infer.dag index f095e9e11c9..1a06bfee447 100644 --- a/src/v4/compiler/04_infer.dag +++ b/src/v4/compiler/04_infer.dag @@ -20,7 +20,6 @@ import v4.std.algebra { list_snoc_item } import v4.std.bounded_lattice_completeness { bounded_lattice_instance_completeness } -import v4.compiler.resolve { ResolvedTree } import v4.std.cardinality { TerminationProof, termination_proof_witness_for_node } import v4.std.collection { List, Map } import v4.std.constraints { @@ -263,7 +262,7 @@ fn infer_partial_bounded_lattice_instances_fold_step( }) } -fn partial_bounded_lattice_instances_in_tree(tree: ResolvedTree) -> List { +fn partial_bounded_lattice_instances_in_tree(tree: Node) -> List { fold_node( n: tree, algebra: NodeFold { @@ -532,7 +531,7 @@ fn infer_entries_fold_step( } } -fn infer_entries_for_tree(tree: ResolvedTree) -> Outcome> { +fn infer_entries_for_tree(tree: Node) -> Outcome> { let partials = partial_bounded_lattice_instances_in_tree(tree: tree) fold_node( n: tree, @@ -547,7 +546,7 @@ fn infer_entries_for_tree(tree: ResolvedTree) -> Outcome Outcome { +fn infer(tree: Node) -> Outcome { match infer_entries_for_tree(tree: tree) { Rejected { diagnostics: r } => Rejected { diagnostics: r } Accepted { value: entries, diagnostics: d } => diff --git a/src/v4/compiler/05_emit.dag b/src/v4/compiler/05_emit.dag index f35eef62d20..1a37508ec76 100644 --- a/src/v4/compiler/05_emit.dag +++ b/src/v4/compiler/05_emit.dag @@ -11,10 +11,11 @@ module v4.compiler.emit import v4.compiler.target_carriers { TargetSource } import v4.compiler.infer { InferredTree } import v4.compiler.translate { - TargetNodeTree, target_serialize_source_from_model, translate } +import v4.std.node { Node } +import v4.std.target_model { TargetModelBundle } import v4.std.diagnostic { Outcome, bind_outcome @@ -22,17 +23,17 @@ import v4.std.diagnostic { import v4.std.target_model { TargetModel } fn serialize_source_for_emitted( - emitted: TargetNodeTree, - target: TargetModel + emitted: Node, + target: TargetModelBundle ) -> Outcome { target_serialize_source_from_model(target: target, emitted: emitted) } -fn serialize_target(tree: TargetNodeTree, target: TargetModel) -> Outcome { +fn serialize_target(tree: Node, target: TargetModelBundle) -> Outcome { serialize_source_for_emitted(emitted: tree, target: target) } fn emit( tree: InferredTree, - target: TargetModel + target: TargetModelBundle ) -> Outcome { bind_outcome( o: translate(tree: tree, target: target), diff --git a/src/v4/compiler/05_eval.dag b/src/v4/compiler/05_eval.dag index 1b04193bdcf..156d1f5d26b 100644 --- a/src/v4/compiler/05_eval.dag +++ b/src/v4/compiler/05_eval.dag @@ -12,7 +12,7 @@ import v4.compiler.infer { inferred_facts_descent, inferred_facts_resolved_type } -import v4.std.algebra { Cons, Empty, fold_list, length } +import v4.std.algebra { Cons, Empty, FreeMonoid, fold_list, length } import v4.std.cardinality { RankingDimension, TerminationProof } import v4.std.collection { List, @@ -630,15 +630,20 @@ fn test_claim_cache_digest_tag_node(tag: Symbol) -> Node { } fn test_claim_evaluation_nodes_digest(c: TestClaim) -> Hash { - fold_list( + node_list_digest( xs: test_claim_evaluation_nodes(c: c), - empty: content_hash(n: test_claim_cache_digest_tag_node(tag: test_claim_cache_claim_digest_tag)), - cons: fn(acc, n) { - combine_hash(a: acc, b: content_hash(n: n)) - } + acc: content_hash(n: test_claim_cache_digest_tag_node(tag: test_claim_cache_claim_digest_tag)) ) } +fn node_list_digest(xs: FreeMonoid, acc: Hash) -> Hash { + match xs { + Empty => acc + Cons { head: n, tail: rest } => + node_list_digest(xs: rest, acc: combine_hash(a: acc, b: content_hash(n: n))) + } +} + // 🟡 derived-operation — feature:T22-EVAL-CACHE-HASHES — bind IRT-4 / TASKS.md T-22 — dissolve-on: content_hash(Node projection of Diagnostic / Correction / Locus / TestClaim) replaces hand-rolled coproduct digest folds below. fn no_correction_reason_digest(reason: NoCorrectionReason) -> Hash { match reason { @@ -804,16 +809,21 @@ fn ranking_dimension_digest(d: RankingDimension) -> Hash { fn termination_proof_digest(proof: TerminationProof) -> Hash { combine_hash( a: ranking_dimension_digest(d: proof.strict), - b: fold_list( + b: ranking_dimension_list_digest( xs: proof.non_increasing, - empty: test_claim_symbol_digest(sym: test_claim_cache_termination_non_increasing_empty_tag), - cons: fn(acc, d) { - combine_hash(a: acc, b: ranking_dimension_digest(d: d)) - } + acc: test_claim_symbol_digest(sym: test_claim_cache_termination_non_increasing_empty_tag) ) ) } +fn ranking_dimension_list_digest(xs: FreeMonoid, acc: Hash) -> Hash { + match xs { + Empty => acc + Cons { head: d, tail: rest } => + ranking_dimension_list_digest(xs: rest, acc: combine_hash(a: acc, b: ranking_dimension_digest(d: d))) + } +} + fn witness_cache_holds_digest(payload: Hash) -> Hash { combine_hash( a: test_claim_symbol_digest(sym: test_claim_cache_witness_holds_tag), diff --git a/src/v4/compiler/06_translate.dag b/src/v4/compiler/06_translate.dag index 13c8bb8ae9c..dd712850922 100644 --- a/src/v4/compiler/06_translate.dag +++ b/src/v4/compiler/06_translate.dag @@ -3,7 +3,7 @@ // Status: W-T-11 — Shape-A MVP-1 grammar-inverse lex walk is exercised by compile-inferred // TestClaims for rust/python/go/cpp/typescript (test/claim/manual/mvp1_*_add_translate.dag); // live translate_node/coerce_grounded_node + child reattachment zip-fold; -// authority_source_text retained on TargetModel as self-host anchor only. +// authority_source_text retained on TargetModelBundle as self-host anchor only. // grammar-inverse serialize uses translate_serialize_measure (node_subtree_count + // translation_rules subtree) — no fixed fuel constant. // Anchor: docs/design-v4-compiler-homomorphism.md Stage 5a; Ratified Q14. @@ -22,6 +22,7 @@ import v4.compiler.target_carriers { TargetSource } import v4.std.target_model { TargetBodiedArrowStatementScaffold, TargetModel, + TargetModelBundle, bodied_arrow_scaffold_from_grammar_relation_row, target_bodied_arrow_compose_statement_tokens, target_model_edge_translation_rules @@ -154,6 +155,7 @@ import v4.std.target_model { target_collection_free_monoid_no_representation_diagnostic, target_collection_select_choice, target_collection_realization_lookup_in_catalog, + target_collection_set_carrier_node, target_carrier_free_monoid_node, target_collection_set_element_type_node, target_collection_free_monoid_element_type_node, @@ -269,7 +271,20 @@ import v4.std.algebra { } import v4.std.logic { Bool } import v4.std.text { String } -type TargetNodeTree = Node + +fn empty_target_source() -> TargetSource { + "" +} + +fn target_model_bundle_as_model(target: TargetModelBundle) -> TargetModel { + TargetModel { + bundle: target.bundle, + lex: target.lex, + binding_spellings: target.binding_spellings, + authority_source_text: target.authority_source_text + } +} + // 🟢 coproduct dissolution type TargetBundleChildLookup = BundleChildMissing @@ -301,7 +316,7 @@ fn node_subtree_count(n: Node) -> Int { } ) } -fn target_translation_rules_budget(target: TargetModel) -> Outcome { +fn target_translation_rules_budget(target: TargetModelBundle) -> Outcome { bind_outcome( o: target_bundle_child(target: target, edge_name: target_model_edge_translation_rules), f: fn(rules) { @@ -312,7 +327,7 @@ fn target_translation_rules_budget(target: TargetModel) -> Outcome { } ) } -fn translate_serialize_measure(target: TargetModel, emitted: Node) -> Outcome { +fn translate_serialize_measure(target: TargetModelBundle, emitted: Node) -> Outcome { bind_outcome( o: target_translation_rules_budget(target: target), f: fn(rules_budget) { @@ -323,7 +338,7 @@ fn translate_serialize_measure(target: TargetModel, emitted: Node) -> Outcome Outcome { +fn token_item_serialize_measure(item: Node, target: TargetModelBundle) -> Outcome { bind_outcome( o: target_translation_rules_budget(target: target), f: fn(rules_budget) { @@ -341,7 +356,7 @@ fn token_list_node_budget(tokens: List) -> Int { cons: fn(acc, item) { acc + node_subtree_count(n: item) } ) } -fn token_sequence_serialize_measure(tokens: List, target: TargetModel) -> Outcome { +fn token_sequence_serialize_measure(tokens: List, target: TargetModelBundle) -> Outcome { bind_outcome( o: target_translation_rules_budget(target: target), f: fn(rules_budget) { @@ -359,7 +374,7 @@ fn token_sequence_serialize_measure(tokens: List, target: TargetModel) -> type TokenSequenceItemKind = TokenSequenceConcreteToken | TokenSequenceNonterminal -fn translate_target_bundle_malformed_diagnostic(target: TargetModel) -> Diagnostic { +fn translate_target_bundle_malformed_diagnostic(target: TargetModelBundle) -> Diagnostic { Diagnostic { reason: translate_target_bundle_malformed, at: node_locus(node: target.bundle), @@ -367,7 +382,7 @@ fn translate_target_bundle_malformed_diagnostic(target: TargetModel) -> Diagnost } } fn translate_target_bundle_duplicate_edge_diagnostic( - target: TargetModel, + target: TargetModelBundle, edge_name: Symbol ) -> Diagnostic { Diagnostic { @@ -1058,7 +1073,7 @@ fn grammar_serialize_source_matches_row( } } fn grammar_inverse_source_validated( - target: TargetModel, + target: TargetModelBundle, emitted: Node ) -> Outcome { bind_outcome( @@ -1177,7 +1192,7 @@ fn target_serialize_bodied_arrow_from_model( fn target_serialize_relation_row_from_model_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, emitted: Node ) -> Outcome { if remaining <= 0 { @@ -1347,7 +1362,7 @@ fn lex_rules_literal_for_class(rules: LexRules, token_class: Symbol) -> Outcome< ) } } -fn token_spelling_from_model(target: TargetModel, token: Node) -> Outcome { +fn token_spelling_from_model(target: TargetModelBundle, token: Node) -> Outcome { bind_outcome( o: concrete_syntax_token_from_node(token: token), f: fn(decoded) { @@ -1379,7 +1394,7 @@ fn token_spelling_from_model(target: TargetModel, token: Node) -> Outcome Outcome { bind_outcome( o: token_sequence_item_kind(item: item), @@ -1393,7 +1408,7 @@ fn token_item_to_source_bounded( } ) } -fn token_item_to_source(item: Node, target: TargetModel) -> Outcome { +fn token_item_to_source(item: Node, target: TargetModelBundle) -> Outcome { bind_outcome( o: token_item_serialize_measure(item: item, target: target), f: fn(measure) { @@ -1404,7 +1419,7 @@ fn token_item_to_source(item: Node, target: TargetModel) -> Outcome, - target: TargetModel + target: TargetModelBundle ) -> Outcome { fold_list( xs: tokens, @@ -1428,7 +1443,7 @@ fn token_sequence_to_source_bounded( } ) } -fn token_sequence_to_source(tokens: List, target: TargetModel) -> Outcome { +fn token_sequence_to_source(tokens: List, target: TargetModelBundle) -> Outcome { bind_outcome( o: token_sequence_serialize_measure(tokens: tokens, target: target), f: fn(measure) { @@ -1437,11 +1452,11 @@ fn token_sequence_to_source(tokens: List, target: TargetModel) -> Outcome< ) } // Shape-A MVP-1 grammar-inverse serialize via token_sequence_to_source for all five -// Shape-A targets (rust/python/go/cpp/typescript TestClaims). TargetModel.authority_source_text +// Shape-A targets (rust/python/go/cpp/typescript TestClaims). TargetModelBundle.authority_source_text // must not substitute for validated emitted Node serialization. fn target_serialize_source_from_model_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, emitted: Node ) -> Outcome { if remaining <= 0 { @@ -1479,7 +1494,7 @@ fn target_serialize_source_from_model_bounded( } } fn target_serialize_source_from_model( - target: TargetModel, + target: TargetModelBundle, emitted: Node ) -> Outcome { bind_outcome( @@ -1489,7 +1504,7 @@ fn target_serialize_source_from_model( } ) } -fn target_bundle_child(target: TargetModel, edge_name: Symbol) -> Outcome { +fn target_bundle_child(target: TargetModelBundle, edge_name: Symbol) -> Outcome { match target.bundle.kind { TypeNode { connective: Conj } => match fold( @@ -1517,7 +1532,7 @@ fn target_bundle_child(target: TargetModel, edge_name: Symbol) -> Outcome outcome_rejected(translate_target_bundle_malformed_diagnostic(target: target)) } } -fn target_bundle_optional_child(target: TargetModel, edge_name: Symbol) -> Outcome { +fn target_bundle_optional_child(target: TargetModelBundle, edge_name: Symbol) -> Outcome { match target.bundle.kind { TypeNode { connective: Conj } => match fold( @@ -1545,7 +1560,7 @@ fn target_bundle_optional_child(target: TargetModel, edge_name: Symbol) -> Outco outcome_rejected(translate_target_bundle_malformed_diagnostic(target: target)) } } -fn target_selection_priority_from_model(target: TargetModel) -> Outcome { +fn target_selection_priority_from_model(target: TargetModelBundle) -> Outcome { bind_outcome( o: target_bundle_child(target: target, edge_name: target_model_edge_selection_policy), f: fn(priority_node) { @@ -1557,7 +1572,7 @@ fn target_selection_priority_from_model(target: TargetModel) -> Outcome { ) } fn coercion_candidates_from_target_model( - target: TargetModel + target: TargetModelBundle ) -> Outcome { bind_outcome( o: target_bundle_child(target: target, edge_name: target_model_edge_declared_inhabitants), @@ -1572,7 +1587,7 @@ fn coercion_candidates_from_target_model( fn coerce_grounded_node( source: Node, tree: InferredTree, - target: TargetModel + target: TargetModelBundle ) -> Outcome { bind_outcome( o: canonical_grounding_for_node(tree: tree, node: source), @@ -1837,7 +1852,7 @@ fn type_expression_projection_from_bundle(bundle: Node) -> Outcome Outcome { +fn type_expression_projection_from_target(target: TargetModelBundle) -> Outcome { bind_outcome( o: target_bundle_child(target: target, edge_name: target_model_edge_type_expression_projection), f: fn(bundle) { type_expression_projection_from_bundle(bundle: bundle) } @@ -2080,7 +2095,7 @@ fn target_collection_realization_from_bundle( ) } -fn collection_realization_from_target(target: TargetModel) -> Outcome { +fn collection_realization_from_target(target: TargetModelBundle) -> Outcome { collection_realization_from_target_carrier( target: target, expected_source_carrier: target_collection_set_carrier_node() @@ -2088,7 +2103,7 @@ fn collection_realization_from_target(target: TargetModel) -> Outcome Outcome { collection_realization_from_target_carrier( target: target, @@ -2097,7 +2112,7 @@ fn free_monoid_collection_realization_from_target( } fn collection_realization_from_target_carrier( - target: TargetModel, + target: TargetModelBundle, expected_source_carrier: Node ) -> Outcome { bind_outcome( @@ -2124,7 +2139,7 @@ fn collection_realization_from_target_carrier( fn project_set_collection_type_node_impl( node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { match target_collection_set_element_type_node(set_node: node) { @@ -2170,7 +2185,7 @@ fn project_set_collection_type_node_impl( fn project_set_collection_type_node( node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { project_set_collection_type_node_impl( @@ -2182,7 +2197,7 @@ fn project_set_collection_type_node( fn project_free_monoid_collection_type_node( node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { match target_collection_free_monoid_element_type_node(free_monoid_node: node) { @@ -2243,6 +2258,10 @@ type EdgeHeadTail { head: Edge tail: List } +type TargetTypeExprArrowParamSlotHeadTail { + head: TargetTypeExprArrowParamSlot + tail: List +} fn edge_list_head_and_tail(edges: List, node: Node) -> Outcome { match list_at_optional(xs: edges, index: 0) { Present { value: head } => @@ -2256,6 +2275,25 @@ fn edge_list_head_and_tail(edges: List, node: Node) -> Outcome, + node: Node +) -> Outcome { + match list_at_optional(xs: xs, index: 0) { + Present { value: head } => + match list_tail(xs: xs) { + TailAbsent => + outcome_rejected(translate_type_expression_shape_missing_diagnostic(node: node)) + TailFound { tail: t } => + Accepted { + value: TargetTypeExprArrowParamSlotHeadTail { head: head, tail: t }, + diagnostics: None + } + } + Absent => + outcome_rejected(translate_type_expression_shape_missing_diagnostic(node: node)) + } +} type TypeExprArrowSplit { inputs: List output: Node @@ -2337,7 +2375,7 @@ fn project_type_expression_children_go( remaining: Int, anchor: Node, children: List, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, acc: List ) -> Outcome> { @@ -2381,7 +2419,7 @@ fn project_type_expression_children( remaining: Int, anchor: Node, children: List, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome> { project_type_expression_children_go( @@ -2390,13 +2428,13 @@ fn project_type_expression_children( children: children, target: target, projection: projection, - acc: Empty + acc: empty_target_source() ) } fn project_type_expression_field_slots_go( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, edges: List, acc: List @@ -2461,7 +2499,7 @@ fn project_type_expression_field_slots_go( fn project_type_expression_field_slots( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome> { project_type_expression_field_slots_go( @@ -2470,14 +2508,14 @@ fn project_type_expression_field_slots( target: target, projection: projection, edges: node.children, - acc: Empty + acc: empty_target_source() ) } fn project_type_expression_variant_slots_go( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, edges: List, acc: List @@ -2523,7 +2561,7 @@ fn project_type_expression_variant_slots_go( fn project_type_expression_variant_slots( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome> { project_type_expression_variant_slots_go( @@ -2532,13 +2570,13 @@ fn project_type_expression_variant_slots( target: target, projection: projection, edges: node.children, - acc: Empty + acc: empty_target_source() ) } fn project_type_expression_conj_fields( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome> { bind_outcome( @@ -2564,7 +2602,7 @@ fn project_type_expression_conj_fields( fn project_type_expression_disj_variants( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome> { bind_outcome( @@ -2591,12 +2629,12 @@ fn project_type_expression_connective_bounded( remaining: Int, node: Node, connective: Connective, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { bind_outcome( o: type_expr_projection_row_closedness_from_target( - target: target, + target: target_model_bundle_as_model(target: target), projection: projection, connective: connective ), @@ -2750,7 +2788,7 @@ fn project_type_expression_connective_bounded( } fn project_type_expression_node( node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { project_type_expression_node_bounded( @@ -2763,7 +2801,7 @@ fn project_type_expression_node( fn project_type_expression_node_bounded( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { if remaining <= 0 { @@ -2783,7 +2821,7 @@ fn project_type_expression_node_bounded( } } } -fn lex_rules_literal(target: TargetModel, token_class: Symbol) -> Outcome { +fn lex_rules_literal(target: TargetModelBundle, token_class: Symbol) -> Outcome { lex_rules_literal_for_class(rules: target.lex, token_class: token_class) } fn type_expr_atom_binding_from_positional( @@ -2823,7 +2861,7 @@ fn type_expr_carrier_identity(node: Node) -> Outcome { _ => type_expr_atom_binding(node: node) } } -fn type_expr_spelling_for_atom(target: TargetModel, node: Node) -> Outcome { +fn type_expr_spelling_for_atom(target: TargetModelBundle, node: Node) -> Outcome { bind_outcome( o: type_expr_atom_binding(node: node), f: fn(binding) { @@ -2853,7 +2891,7 @@ fn serialize_type_expr_emitted_positional_head_tail(node: Node) -> Outcome, @@ -2976,7 +3014,7 @@ fn serialize_type_expr_args_go( } fn serialize_type_expr_args_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetGenericApply, args: List, @@ -2989,12 +3027,12 @@ fn serialize_type_expr_args_bounded( form: form, args: args, anchor: anchor, - acc: Empty + acc: empty_target_source() ) } fn serialize_type_expr_separated_go( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, separator: Symbol, items: List, @@ -3056,7 +3094,7 @@ fn serialize_type_expr_separated_go( } fn serialize_type_expr_separated_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, separator: Symbol, items: List, @@ -3069,11 +3107,11 @@ fn serialize_type_expr_separated_bounded( separator: separator, items: items, anchor: anchor, - acc: Empty + acc: empty_target_source() ) } -fn serialize_type_expr_record_field_label(target: TargetModel, edge: Edge) -> Outcome { +fn serialize_type_expr_record_field_label(target: TargetModelBundle, edge: Edge) -> Outcome { match edge.label { Named { name: label } => match map_get(target.binding_spellings, label) { @@ -3098,7 +3136,7 @@ fn serialize_type_expr_record_field_label(target: TargetModel, edge: Edge) -> Ou fn serialize_type_expr_record_fields_go( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, separator: Symbol, field_label_separator: Symbol, @@ -3178,7 +3216,7 @@ fn serialize_type_expr_record_fields_go( fn serialize_type_expr_record_fields_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, separator: Symbol, field_label_separator: Symbol, @@ -3193,13 +3231,13 @@ fn serialize_type_expr_record_fields_bounded( field_label_separator: field_label_separator, fields: fields, anchor: anchor, - acc: Empty + acc: empty_target_source() ) } fn serialize_type_expr_record_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetGenericApply, node: Node @@ -3246,7 +3284,7 @@ fn serialize_type_expr_record_bounded( } fn serialize_type_expr_sum_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetSumTypeShape, node: Node @@ -3266,7 +3304,7 @@ fn serialize_type_expr_sum_bounded( ) } fn serialize_type_expr_arrow_param_spelling( - target: TargetModel, + target: TargetModelBundle, label: Symbol ) -> Outcome { match map_get(target.binding_spellings, label) { @@ -3288,7 +3326,7 @@ fn serialize_type_expr_arrow_param_spelling( fn serialize_type_expr_arrow_param_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetFunctionTypeShape, slot: TargetTypeExprArrowParamSlot @@ -3328,7 +3366,7 @@ fn serialize_type_expr_arrow_param_bounded( fn serialize_type_expr_arrow_params_go( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetFunctionTypeShape, params: List, @@ -3343,7 +3381,7 @@ fn serialize_type_expr_arrow_params_go( Accepted { value: acc, diagnostics: None } } else { bind_outcome( - o: list_head_and_tail(xs: params, node: anchor), + o: target_type_expr_arrow_param_slot_head_and_tail(xs: params, node: anchor), f: fn(split) { bind_outcome( o: serialize_type_expr_arrow_param_bounded( @@ -3392,7 +3430,7 @@ fn serialize_type_expr_arrow_params_go( fn serialize_type_expr_arrow_named_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetFunctionTypeShape, node: Node @@ -3414,7 +3452,7 @@ fn serialize_type_expr_arrow_named_bounded( form: form, params: params, anchor: node, - acc: Empty + acc: empty_target_source() ), f: fn(params_source) { bind_outcome( @@ -3463,7 +3501,7 @@ fn serialize_type_expr_arrow_named_bounded( fn serialize_type_expr_arrow_input_wrapped( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetFunctionTypeShape, input_node: Node @@ -3499,7 +3537,7 @@ fn serialize_type_expr_arrow_input_wrapped( } fn serialize_type_expr_arrow_inputs_go( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetFunctionTypeShape, inputs: List, @@ -3562,7 +3600,7 @@ fn serialize_type_expr_arrow_inputs_go( } fn serialize_type_expr_arrow_inputs_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetFunctionTypeShape, inputs: List, @@ -3575,12 +3613,12 @@ fn serialize_type_expr_arrow_inputs_bounded( form: form, inputs: inputs, anchor: anchor, - acc: Empty + acc: empty_target_source() ) } fn serialize_type_expr_arrow_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, form: TargetFunctionTypeShape, node: Node @@ -3649,7 +3687,7 @@ fn serialize_type_expr_arrow_bounded( } fn serialize_type_expr_emitted_wire_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, wire: TargetTypeExpression ) -> Outcome { @@ -3700,7 +3738,7 @@ fn serialize_type_expr_emitted_wire_bounded( } fn serialize_type_expr_emitted_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, emitted: Node ) -> Outcome { @@ -3728,7 +3766,7 @@ fn translate_outcome_is_catalog_lookup_miss( diagnostics.head.reason == target_atom_realization_lookup_miss } -fn translate_sg_rc_bundle_edge_present(target: TargetModel, edge_name: Symbol) -> Outcome { +fn translate_sg_rc_bundle_edge_present(target: TargetModelBundle, edge_name: Symbol) -> Outcome { match target_bundle_optional_child(target: target, edge_name: edge_name) { Accepted { value: optional_child, diagnostics: d } => match optional_child { @@ -3741,7 +3779,7 @@ fn translate_sg_rc_bundle_edge_present(target: TargetModel, edge_name: Symbol) - // Accepted false => no SG-RC edges (skip consumer); true => apply catalog; Rejected => malformed/partial bundle. fn translate_sg_rc_bundle_apply_disposition( - target: TargetModel, + target: TargetModelBundle, source_carrier: Node ) -> Outcome { bind_outcome( @@ -3772,7 +3810,7 @@ fn translate_sg_rc_bundle_apply_disposition( } fn translate_reference_layer_tokens_from_target( - target: TargetModel + target: TargetModelBundle ) -> Outcome { bind_outcome( o: target_bundle_child(target: target, edge_name: target_model_edge_reference_layer_tokens), @@ -3781,7 +3819,7 @@ fn translate_reference_layer_tokens_from_target( } fn translate_use_site_ownership_catalog_from_model( - target: TargetModel, + target: TargetModelBundle, source_carrier: Node ) -> Outcome { match target_bundle_optional_child( @@ -3804,7 +3842,7 @@ fn translate_use_site_ownership_catalog_from_model( // (a target without value-semantics modeling behaves exactly as before: every // carrier flows to the reference catalog). Decoded to the Atom-identity list the // authority lookup matches on. -fn translate_value_semantics_carriers_from_model(target: TargetModel) -> Outcome> { +fn translate_value_semantics_carriers_from_model(target: TargetModelBundle) -> Outcome> { match target_bundle_optional_child( target: target, edge_name: target_model_edge_value_semantics_carriers @@ -3822,7 +3860,7 @@ fn translate_value_semantics_carriers_from_model(target: TargetModel) -> Outcome fn translate_apply_use_site_ownership_to_projected_type( projected: Node, source_carrier: Node, - target: TargetModel, + target: TargetModelBundle, use_site: TargetOwnershipUseSite ) -> Outcome { translate_apply_use_site_ownership_to_type_shell( @@ -3838,7 +3876,7 @@ fn translate_apply_use_site_ownership_to_projected_type( fn translate_apply_use_site_ownership_to_projected_boundary( projected: Node, source_for_binding: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, use_site: TargetOwnershipUseSite ) -> Outcome { @@ -3867,7 +3905,7 @@ fn translate_apply_use_site_ownership_to_projected_boundary( fn project_type_expression_arrow_emitted_from_original_split( original_split: TypeExprArrowSplit, anchor: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { bind_outcome( @@ -3893,7 +3931,7 @@ fn translate_project_arrow_input_types_go( remaining: Int, anchor: Node, original_inputs: List, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, acc: List ) -> Outcome> { @@ -3941,7 +3979,7 @@ fn translate_project_arrow_input_types_go( fn translate_project_arrow_split_types( original_split: TypeExprArrowSplit, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, anchor: Node ) -> Outcome { @@ -3952,7 +3990,7 @@ fn translate_project_arrow_split_types( original_inputs: original_split.inputs, target: target, projection: projection, - acc: Empty + acc: empty_target_source() ), f: fn(wrapped_inputs) { bind_outcome( @@ -3989,7 +4027,7 @@ fn translate_project_arrow_split_types( fn translate_apply_use_site_ownership_to_type_shell( shell: Node, source_carrier: Node, - target: TargetModel, + target: TargetModelBundle, use_site: TargetOwnershipUseSite ) -> Outcome { match translate_sg_rc_bundle_apply_disposition( @@ -4078,7 +4116,7 @@ fn function_boundary_site_to_ownership_use_site( // signature catalog OR no row matches (both fall back to the SG-2/binding_spellings path); Rejected // only on a genuine decode/ambiguity error. fn translate_target_function_signature_realization_for_boundary( - target: TargetModel, + target: TargetModelBundle, emitted: Node, boundary_site: FunctionBoundarySite ) -> Outcome> { @@ -4098,7 +4136,7 @@ fn translate_target_function_signature_realization_for_boundary( catalog: catalog, source_carrier: translate_boundary_source_carrier_node(binding: binding), boundary_site: boundary_site, - host_target_model: target + host_target_model: target_model_bundle_as_model(target: target) ) { Accepted { value: row, diagnostics: _ } => outcome_accepted(optional_present(row)) @@ -4120,7 +4158,7 @@ fn translate_target_function_signature_realization_for_boundary( // boundary role, then serialize the emitted wire (SG-RC + SG-2; no spelling-only bypass). fn serialize_type_expr_boundary_atom_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, boundary_site: FunctionBoundarySite, emitted: Node @@ -4172,7 +4210,7 @@ fn serialize_type_expr_boundary_atom_bounded( // Atom boundaries consult signature realization; composite boundary types serialize normally. fn serialize_type_expr_boundary_bounded( remaining: Int, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, boundary_site: FunctionBoundarySite, emitted: Node @@ -4207,7 +4245,7 @@ fn serialize_type_expr_boundary_bounded( } } -fn translate_coerced_shell_base(coerced: Node, target: TargetModel) -> Outcome { +fn translate_coerced_shell_base(coerced: Node, target: TargetModelBundle) -> Outcome { match translate_target_atom_realization_for_carrier( target: target, source_carrier: coerced @@ -4228,7 +4266,7 @@ fn translate_coerced_shell_base(coerced: Node, target: TargetModel) -> Outcome Outcome { translate_coerced_shell_at_use_site_from_source( @@ -4242,7 +4280,7 @@ fn translate_coerced_shell_at_use_site( fn translate_coerced_shell_at_use_site_from_source( coerced: Node, ownership_source_carrier: Node, - target: TargetModel, + target: TargetModelBundle, use_site: TargetOwnershipUseSite ) -> Outcome { match translate_coerced_type_shell_from_source( @@ -4267,7 +4305,7 @@ fn translate_coerced_shell_at_use_site_from_source( fn translate_coerced_type_shell_from_source( source_carrier: Node, coerced: Node, - target: TargetModel + target: TargetModelBundle ) -> Outcome { match source_carrier.kind { TypeNode { connective: Instantiation } => @@ -4285,7 +4323,7 @@ fn translate_coerced_type_shell_from_source( } } -fn translate_coerced_shell(coerced: Node, target: TargetModel) -> Outcome { +fn translate_coerced_shell(coerced: Node, target: TargetModelBundle) -> Outcome { translate_coerced_shell_at_use_site( coerced: coerced, target: target, @@ -4300,7 +4338,7 @@ fn translate_use_site_ownership_source_carrier(source: Node, coerced: Node) -> N } } fn target_atom_realizations_catalog_from_model( - target: TargetModel, + target: TargetModelBundle, source_carrier: Node ) -> Outcome { match target_bundle_optional_child( @@ -4321,7 +4359,7 @@ fn target_atom_realizations_catalog_from_model( } } fn translate_target_atom_realization_for_carrier( - target: TargetModel, + target: TargetModelBundle, source_carrier: Node ) -> Outcome { bind_outcome( @@ -4333,7 +4371,7 @@ fn translate_target_atom_realization_for_carrier( target_atom_realization_lookup_in_catalog_node( catalog: catalog, source_carrier: source_carrier, - host_target_model: target + host_target_model: target_model_bundle_as_model(target: target) ) } ) @@ -4357,7 +4395,7 @@ fn translate_shell_attach_value_expression(shell: Node, value: Node) -> Node { fn translate_apply_use_site_ownership_to_value_expression( expr: TargetValueExpression, source_carrier: Node, - target: TargetModel, + target: TargetModelBundle, use_site: TargetOwnershipUseSite ) -> Outcome { match translate_sg_rc_bundle_apply_disposition( @@ -4411,7 +4449,7 @@ fn translate_apply_use_site_ownership_to_value_expression( fn translate_atom_realization_value_from_source_at_use_site( source: Node, coerced: Node, - target: TargetModel, + target: TargetModelBundle, use_site: TargetOwnershipUseSite ) -> Outcome> { match translate_target_atom_realization_for_carrier( @@ -4457,7 +4495,7 @@ fn translate_atom_realization_value_from_source_at_use_site( fn translate_coerced_with_atom_realization_at_use_site( source: Node, coerced: Node, - target: TargetModel, + target: TargetModelBundle, use_site: TargetOwnershipUseSite, pending: Diagnostics ) -> Outcome { @@ -4515,7 +4553,7 @@ fn translate_coerced_with_atom_realization_at_use_site( fn translate_coerced_with_atom_realization( source: Node, coerced: Node, - target: TargetModel, + target: TargetModelBundle, pending: Diagnostics ) -> Outcome { translate_coerced_with_atom_realization_at_use_site( @@ -4540,7 +4578,7 @@ fn translate_computation_fold_init(node: Node) -> Outcome { fn translate_fold_init( node: Node, tree: InferredTree, - target: TargetModel + target: TargetModelBundle ) -> Outcome { match node.kind { TypeNode { connective: _ } => translate_type_fold_init(node: node) @@ -4595,7 +4633,7 @@ fn translate_mvp1_coerce_from_grounding_or_evidence( fn translate_mvp1_fold_init( node: Node, tree: InferredTree, - target: TargetModel + target: TargetModelBundle ) -> Outcome { match node.kind { TypeNode { connective: Arrow } => @@ -4638,7 +4676,7 @@ fn translate_mvp1_fold_init( // the target's grammar relation? Accepted(row) => the node is grammar-fixtured and must // serialize via the mode-1 whole-node match (grammar_relation_row_for_emitted :536 -> // pre-baked tokens); Rejected => no row, fall through to the projection / mode-2 path. -fn translate_grammar_relation_row_match(target: TargetModel, emitted: Node) -> Outcome { +fn translate_grammar_relation_row_match(target: TargetModelBundle, emitted: Node) -> Outcome { bind_outcome( o: target_bundle_child(target: target, edge_name: target_model_edge_translation_rules), f: fn(rules) { grammar_relation_row_for_emitted(rules: rules, emitted: emitted) } @@ -4647,7 +4685,7 @@ fn translate_grammar_relation_row_match(target: TargetModel, emitted: Node) -> O fn translate_type_expression_tree( node: Node, tree: InferredTree, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { if arrow_has_transform_body(arrow: node) { @@ -4685,7 +4723,7 @@ fn translate_type_expression_tree( fn translate_node_with_projection( node: Node, tree: InferredTree, - target: TargetModel + target: TargetModelBundle ) -> Outcome { bind_outcome( o: type_expression_projection_from_target(target: target), @@ -4720,7 +4758,7 @@ fn translate_node_with_projection( fn project_type_expression_subtree( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome { if remaining <= 0 { @@ -4755,7 +4793,7 @@ fn project_type_expression_subtree( fn project_type_expression_children_in_node_go( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection, edges: List, acc: List @@ -4796,7 +4834,7 @@ fn project_type_expression_children_in_node_go( fn project_type_expression_children_in_node( remaining: Int, node: Node, - target: TargetModel, + target: TargetModelBundle, projection: TargetTypeExpressionProjection ) -> Outcome> { project_type_expression_children_in_node_go( @@ -4805,13 +4843,13 @@ fn project_type_expression_children_in_node( target: target, projection: projection, edges: node.children, - acc: Empty + acc: empty_target_source() ) } fn translate_node_computation( node: Node, tree: InferredTree, - target: TargetModel + target: TargetModelBundle ) -> Outcome { fold_node( n: node, @@ -4824,7 +4862,7 @@ fn translate_node_computation( fn translate_node_mvp1( node: Node, tree: InferredTree, - target: TargetModel + target: TargetModelBundle ) -> Outcome { fold_node( n: node, @@ -4837,7 +4875,7 @@ fn translate_node_mvp1( fn translate_node( node: Node, tree: InferredTree, - target: TargetModel + target: TargetModelBundle ) -> Outcome { match target_bundle_child_optional_type_expr_projection(target: target) { Accepted { value: ProjectionPresent, diagnostics: _ } => @@ -4848,12 +4886,12 @@ fn translate_node( Rejected { diagnostics: r } } } -// 🟡 gated — coproduct-dissolution interim (docs/modeling-discipline.md Practice 4/9) — feature:sg-2-mvp1-projection-absent-shim — consumer:translate_node — bind PR #3962 / docs/planning/v4-sg2-type-expression-projection-worksheet-2026-05-30.md — owner:Target Realization (SG-2) — lane:extdeps TargetModel row rollout — dissolve-on-arrival: every v4.extdeps.languages.* TargetModel bundle carries target_model_edge_type_expression_projection; delete ProjectionAbsent arm, translate_node_mvp1, and TypeExprProjectionPresence from translate_node — forbidden: steady-state dual translate paths or new ProjectionAbsent match arms outside this gate. +// 🟡 gated — coproduct-dissolution interim (docs/modeling-discipline.md Practice 4/9) — feature:sg-2-mvp1-projection-absent-shim — consumer:translate_node — bind PR #3962 / docs/planning/v4-sg2-type-expression-projection-worksheet-2026-05-30.md — owner:Target Realization (SG-2) — lane:extdeps TargetModelBundle row rollout — dissolve-on-arrival: every v4.extdeps.languages.* TargetModelBundle bundle carries target_model_edge_type_expression_projection; delete ProjectionAbsent arm, translate_node_mvp1, and TypeExprProjectionPresence from translate_node — forbidden: steady-state dual translate paths or new ProjectionAbsent match arms outside this gate. type TypeExprProjectionPresence = ProjectionPresent | ProjectionAbsent fn target_bundle_child_optional_type_expr_projection( - target: TargetModel + target: TargetModelBundle ) -> Outcome { match target_bundle_optional_child( target: target, @@ -4896,8 +4934,8 @@ fn translate_fold_step( } fn translate( tree: InferredTree, - target: TargetModel -) -> Outcome { + target: TargetModelBundle +) -> Outcome { translate_node(node: tree.root, tree: tree, target: target) } diff --git a/src/v4/compiler/emit_host.dag b/src/v4/compiler/emit_host.dag index b4d5e6b1554..2e86929f98b 100644 --- a/src/v4/compiler/emit_host.dag +++ b/src/v4/compiler/emit_host.dag @@ -62,7 +62,7 @@ import v4.std.integer { Int } import v4.std.machine { Byte } import v4.std.node { Atom, Node, Symbol, TypeNode, SyntheticOccurrence } import v4.std.runtime { RuntimeValue, RuntimePrimitive } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.std.text { String } import v4.std.verdict { Verdict, Pass, Fail, Deferred, verdict_fail } import v4.std.verification { @@ -80,6 +80,9 @@ data emit_host_run_unsupported_target: Symbol = emit_host_run_unsupported_target data emit_host_emit_vs_eval_deferred: Symbol = emit_host_emit_vs_eval_deferred data emit_host_exit_not_ok: Symbol = emit_host_exit_not_ok data emit_host_rust_i64_symbol: Symbol = emit_host_rust_i64_symbol +// 🟡 coproduct dissolution — feature:emit-host-rust-authority-pin (joint spec §4.2 A3); +// W3: executable transport in `emit_host_bridge.rs`; substrate row defers until T-22 dispatch. +// dissolve-on: structural `runtime_row` on TargetModelBundle replaces `authority_source_text` pin match. data emit_host_ts_i32_symbol: Symbol = emit_host_ts_i32_symbol // 🟡 gated — per-target host-emission source-text pins (P2 §314: target knowledge in compiler code; these literals DUPLICATE the authority of extdeps/languages/*::*_mvp1_source_text) — feature: T-22 host-emission TargetModel dissolution — bind: gunbc#4674 — dissolve-on-arrival: promote a typed runtime_row onto TargetModel; point these pins at extdeps/languages/*::*_mvp1_source_text instead of local copies, then delete them; replace the per-target if-chains below (and their mirror in emit_host_eval.rs + the python hand-reification at emit_host_eval.rs:1022-1061) with a generic row-lookup. forbidden: adding a 5th per-target pin/arm without the dissolution. data emit_host_rust_authority_pin: String = "fn add(x: i32, y: i32) -> i32 { x + y }" @@ -154,7 +157,7 @@ fn emit_host_ts_i32_node() -> Node { } fn emit_host_receipt_from_source( - target: TargetModel, + target: TargetModelBundle, source: TargetSource, exit: HostExit, stdout_bytes: ByteString, @@ -171,6 +174,15 @@ fn emit_host_receipt_from_source( } } +fn emit_host_target_model_bundle_as_model(target: TargetModelBundle) -> TargetModel { + TargetModel { + bundle: target.bundle, + lex: target.lex, + binding_spellings: target.binding_spellings, + authority_source_text: target.authority_source_text + } +} + fn runtime_value_parse_rust(bytes: ByteString) -> Outcome { if count(bytes) == 5 { Accepted { @@ -215,7 +227,7 @@ fn runtime_value_parse_signed_i32_le(bytes: ByteString) -> Outcome } } -fn runtime_value_parse(target: TargetModel, stdout: HostRunStdout) -> Outcome { +fn runtime_value_parse(target: TargetModelBundle, stdout: HostRunStdout) -> Outcome { // 🟡 gated — per-target host-emission discriminator (P2 §314: target knowledge in compiler code; this if-chain branches on per-target authority_source_text pins, cost-of-change=N) — feature: T-22 host-emission TargetModel dissolution — bind: gunbc#4674 — dissolve-on-arrival: promote a typed runtime_row onto TargetModel and replace this per-target if-chain (and its mirror in emit_host_eval.rs + the python hand-reification at emit_host_eval.rs:1022-1061) with a generic row-lookup. forbidden: adding a 5th per-target arm without the dissolution. if target.authority_source_text == emit_host_rust_authority_pin { runtime_value_parse_rust(bytes: stdout.bytes) @@ -240,7 +252,7 @@ fn runtime_value_signed_i32_le_as_int(value: RuntimeValue) -> Outcome { // Substrate row: body stays fail-closed; T-22 eval intercepts Callable dispatch to // `tools/emit_host_runner` (no fabricated receipt in `.dag`). Executable proof: `emit_host_eval.rs`. fn run_emit_host_rust( - target: TargetModel, + target: TargetModelBundle, source: TargetSource, fixture_inputs: Inputs ) -> Outcome { @@ -253,7 +265,7 @@ fn run_emit_host_rust( // in `emit_host_eval.rs` (rust/go route through substrate `emit_host_receipt_from_source`). // Asymmetry is tracked under T-PB-B until python receipt assembly moves into `.dag`. fn run_emit_host_python( - target: TargetModel, + target: TargetModelBundle, source: TargetSource, fixture_inputs: Inputs ) -> Outcome { @@ -263,7 +275,7 @@ fn run_emit_host_python( } fn run_emit_host_go( - target: TargetModel, + target: TargetModelBundle, source: TargetSource, fixture_inputs: Inputs ) -> Outcome { @@ -285,18 +297,18 @@ fn run_host_process( } fn run_emit_host( - target: TargetModel, + target: TargetModelBundle, source: TargetSource, fixture_inputs: Inputs ) -> Outcome { // 🟡 gated — per-target host-emission discriminator (P2 §314: target knowledge in compiler code; this if-chain branches on per-target authority_source_text pins, cost-of-change=N) — feature: T-22 host-emission TargetModel dissolution — bind: gunbc#4674 — dissolve-on-arrival: promote a typed runtime_row onto TargetModel and replace this per-target if-chain (and its mirror in emit_host_eval.rs + the python hand-reification at emit_host_eval.rs:1022-1061) with a generic row-lookup. forbidden: adding a 5th per-target arm without the dissolution. if target.authority_source_text == ts_mvp1_source_text_authority() { - run_host_process( - descriptor: ts_host_transport_mvp1_descriptor(), - target: target, - source: source, - fixture_inputs: fixture_inputs - ) + run_host_process( + descriptor: ts_host_transport_mvp1_descriptor(), + target: emit_host_target_model_bundle_as_model(target: target), + source: source, + fixture_inputs: fixture_inputs + ) } else if target.authority_source_text == emit_host_rust_authority_pin { run_emit_host_rust(target: target, source: source, fixture_inputs: fixture_inputs) } else if target.authority_source_text == emit_host_python_authority_pin { @@ -312,7 +324,7 @@ fn run_emit_host( fn run_test_claim_emit_vs_eval_verdict( subject: TestClaimEvalSubject, - target: TargetModel, + target: TargetModelBundle, host_receipt: EmitHostRunReceipt, host_actual: RuntimeValue, expected: Outcome @@ -347,7 +359,7 @@ fn run_test_claim_emit_vs_eval_verdict( // expected_eval_root: rhs / expected_value (matches run_test_claim_runtime_assert). fn run_test_claim_emit_vs_eval_for_claim( subject: TestClaimEvalSubject, - target: TargetModel, + target: TargetModelBundle, claim_input_root: Node, expected_eval_root: Node ) -> Verdict, RuntimeValue> { @@ -403,7 +415,7 @@ fn run_test_claim_emit_vs_eval_for_claim( fn run_test_claim_emit_vs_eval_run( subject: TestClaimEvalSubject, - target: TargetModel, + target: TargetModelBundle, verdict: Verdict, RuntimeValue> ) -> TestClaimRun { TestClaimRun { @@ -414,7 +426,7 @@ fn run_test_claim_emit_vs_eval_run( fn run_test_claim_emit_vs_eval( subject: TestClaimEvalSubject, - target: TargetModel + target: TargetModelBundle ) -> TestClaimRun { match subject.claim { EqualsClaim { rhs: rhs, label: _, anchor: _, lhs: lhs, classification: _ } => diff --git a/src/v4/compiler/self_host.dag b/src/v4/compiler/self_host.dag index d86c57704fa..9e0415b62e2 100644 --- a/src/v4/compiler/self_host.dag +++ b/src/v4/compiler/self_host.dag @@ -26,25 +26,25 @@ type CoreNode = Node type SourceModels { - model_corpus: List + model_corpus: List } type StructurallyEqual { - left: CoreNode - right: CoreNode + left: Node + right: Node } type BootstrapRoundtripEqual { - produced_stage: CoreNode - expected_stage: CoreNode + produced_stage: Node + expected_stage: Node } type FixedPointEqual { - emitted_stage: CoreNode - reference_stage: CoreNode + emitted_stage: Node + reference_stage: Node } @@ -83,8 +83,8 @@ fn self_host_runner_not_realized_diagnostic() -> Diagnostic { // 🟡 scaffold shape — all sub-checks return Violates; not yet called from self_host_fixed_point_validate // (the main entry point returns fail-closed directly until execution substrate lands). fn candidate_promotion_witness( - stage1_candidate: CoreNode, - reference_stage1: CoreNode + stage1_candidate: Node, + reference_stage1: Node ) -> PromotionWitness { PromotionWitness { candidate_bootstrap_roundtrip_sub_check: bootstrap_roundtrip_scaffold( @@ -100,8 +100,8 @@ fn candidate_promotion_witness( fn bootstrap_roundtrip_scaffold( - produced_stage: CoreNode, - expected_stage: CoreNode + produced_stage: Node, + expected_stage: Node ) -> BootstrapRoundtripCheck { Violates { diagnostic: Diagnostic { @@ -114,8 +114,8 @@ fn bootstrap_roundtrip_scaffold( fn fixed_point_scaffold( - emitted_stage: CoreNode, - reference_stage: CoreNode + emitted_stage: Node, + reference_stage: Node ) -> FixedPointCheck { Violates { diagnostic: Diagnostic { @@ -128,8 +128,8 @@ fn fixed_point_scaffold( fn stage_emission_equality_scaffold( - emitted_candidate: CoreNode, - reference_stage1: CoreNode + emitted_candidate: Node, + reference_stage1: Node ) -> StageEmissionEquality { Violates { diagnostic: Diagnostic { @@ -142,9 +142,9 @@ fn stage_emission_equality_scaffold( fn self_host_fixed_point_validate( - stage1_candidate: CoreNode, + stage1_candidate: Node, source_models: SourceModels, - reference_stage1: CoreNode + reference_stage1: Node ) -> Outcome { Rejected { diagnostics: diagnostics_singleton(d: self_host_runner_not_realized_diagnostic()) diff --git a/src/v4/compiler/source_authority.dag b/src/v4/compiler/source_authority.dag index e1ac65a354c..1ade91cf483 100644 --- a/src/v4/compiler/source_authority.dag +++ b/src/v4/compiler/source_authority.dag @@ -32,7 +32,7 @@ import v4.std.diagnostic { import v4.std.grammar { ParseTree } import v4.std.node { Node, Symbol, canonicalize_node_strip_provenance } import v4.std.provenance { SpanIndex } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.compiler.target_carriers { TargetSource } import v4.compiler.translate { target_serialize_source_from_model } import v4.std.text { String } @@ -41,6 +41,34 @@ import v4.std.witness { Holds, Violates, Witness } type DagSource = String +// 🟡 transparent carrier boundary adapters — owner: Mgr-SOUNDNESS with +// Mgr-SELFHOST; lane: v4 tree-carrier alias collapse after #4587 BindingId. +// These are call-boundary conversions between declared transparent carriers +// (TargetSource, TargetModelBundle, ParseTree, NormalizedTree, ResolvedTree) +// and the current stage APIs that still consume their raw structural carriers. +// They do not branch, compare, or originate identity. Dissolve when the stage +// signatures accept the declared carriers directly, or when the aliases collapse +// to one canonical carrier in the v4 source-authority model. +fn target_source_to_string(source: TargetSource) -> String { + source +} + +fn target_model_to_bundle(target: TargetModel) -> TargetModelBundle { + target +} + +fn parse_tree_to_node(tree: ParseTree) -> Node { + tree +} + +fn normalized_tree_to_node(tree: NormalizedTree) -> Node { + tree +} + +fn resolved_tree_to_node(tree: ResolvedTree) -> Node { + tree +} + type DagSourceAst { tree: ParseTree } @@ -54,7 +82,7 @@ type DagSemanticIr { } type DagSourceReadWitness { - source: DagSource + source: String artifact: Artifact // R3 gate #31: Symbol compilation-unit authority on Textual locus in OriginEvent::FromSource // recorded in SpanIndex at parse-mint (02_parse.dag parse_mint_from_source). @@ -90,13 +118,13 @@ type NormalizedDagSourceParsePrintLaw { } type CanonicalDagSourceEmissionLaw { - canonical_source: DagSource + canonical_source: String serializer_law: DeterministicDagSourceSerializerLaw parse_print_law: NormalizedDagSourceParsePrintLaw } type SourceAuthorityRoundTripLaw { - canonical_source: DagSource + canonical_source: String source_law: SourceAstEqual semantic_law: SemanticIrEqual canonical_source_law: CanonicalDagSourceEmissionLaw @@ -121,7 +149,7 @@ fn source_authority_diagnostic(reason: Symbol) -> Diagnostic { fn parse_dag_source_ast_with_model( - source: DagSource, + source: String, compilation_unit: Symbol, lm: DagLanguageModel ) -> Outcome { @@ -139,7 +167,7 @@ fn parse_dag_source_ast_with_model( } -fn parse_dag_source_ast(source: DagSource) -> Outcome { +fn parse_dag_source_ast(source: String) -> Outcome { parse_dag_source_ast_with_model( source: source, compilation_unit: source_authority_port, @@ -150,7 +178,7 @@ fn parse_dag_source_ast(source: DagSource) -> Outcome { fn normalize_dag_source_ast(ast: DagSourceAst) -> Outcome { bind_outcome( - o: normalize(parse_tree: ast.tree), + o: normalize(parse_tree: parse_tree_to_node(tree: ast.tree)), f: fn(normalized) { outcome_accepted(value: NormalizedDagSourceAst { tree: normalized }) } @@ -160,7 +188,7 @@ fn normalize_dag_source_ast(ast: DagSourceAst) -> Outcome Outcome { bind_outcome( - o: normalize(parse_tree: ast.tree), + o: normalize(parse_tree: parse_tree_to_node(tree: ast.tree)), f: fn(normalized) { bind_outcome( o: resolve(tree: normalized, lm: lm), @@ -174,7 +202,7 @@ fn semantic_ir_from_ast_with_model(ast: DagSourceAst, lm: DagLanguageModel) -> O fn semantic_ir_from_source_with_model( - source: DagSource, + source: String, compilation_unit: Symbol, lm: DagLanguageModel ) -> Outcome { @@ -191,7 +219,7 @@ fn semantic_ir_from_source_with_model( } -fn semantic_ir_from_source(source: DagSource) -> Outcome { +fn semantic_ir_from_source(source: String) -> Outcome { semantic_ir_from_source_with_model( source: source, compilation_unit: source_authority_port, @@ -278,7 +306,7 @@ fn source_ast_equal_witness( original: DagSourceAst, reparsed: DagSourceAst ) -> Witness { - if source_authority_node_equal(left: original.tree, right: reparsed.tree) { + if source_authority_node_equal(left: parse_tree_to_node(tree: original.tree), right: parse_tree_to_node(tree: reparsed.tree)) { Holds { value: SourceAstEqual { original: original, reparsed: reparsed } } } else { Violates { @@ -292,7 +320,7 @@ fn normalized_source_ast_equal_witness( original: NormalizedDagSourceAst, reparsed: NormalizedDagSourceAst ) -> Witness { - if source_authority_node_equal(left: original.tree, right: reparsed.tree) { + if source_authority_node_equal(left: normalized_tree_to_node(tree: original.tree), right: normalized_tree_to_node(tree: reparsed.tree)) { Holds { value: NormalizedSourceAstEqual { original: original, reparsed: reparsed } } } else { Violates { @@ -306,7 +334,7 @@ fn semantic_ir_equal_witness( original: DagSemanticIr, reparsed: DagSemanticIr ) -> Witness { - if source_authority_node_equal(left: original.tree, right: reparsed.tree) { + if source_authority_node_equal(left: resolved_tree_to_node(tree: original.tree), right: resolved_tree_to_node(tree: reparsed.tree)) { Holds { value: SemanticIrEqual { original: original, reparsed: reparsed } } } else { Violates { @@ -317,8 +345,8 @@ fn semantic_ir_equal_witness( fn deterministic_dag_source_serializer_witness( - first: DagSource, - second: DagSource + first: String, + second: String ) -> Witness { if first == second { Holds { value: DeterministicDagSourceSerializerLaw {} } @@ -332,8 +360,8 @@ fn deterministic_dag_source_serializer_witness( fn canonical_dag_source_emission_law_from_parts( original_ast: DagSourceAst, - canonical_source_first: DagSource, - canonical_source_second: DagSource, + canonical_source_first: String, + canonical_source_second: String, reparsed_ast: DagSourceAst ) -> Outcome> { bind_outcome( @@ -380,7 +408,7 @@ fn canonical_dag_source_emission_law_from_parts( fn source_authority_law_from_parts( original_ast: DagSourceAst, - canonical_source: DagSource, + canonical_source: String, reparsed_ast: DagSourceAst, original_ir: DagSemanticIr, reparsed_ir: DagSemanticIr, @@ -412,7 +440,7 @@ fn source_authority_law_from_parts( fn source_authority_round_trip_with_model( - source: DagSource, + source: String, canonical_source_target: TargetModel, lm: DagLanguageModel ) -> Outcome> { @@ -428,19 +456,19 @@ fn source_authority_round_trip_with_model( f: fn(original_ir) { bind_outcome( o: target_serialize_source_from_model( - target: canonical_source_target, - emitted: original_ir.tree + target: target_model_to_bundle(target: canonical_source_target), + emitted: resolved_tree_to_node(tree: original_ir.tree) ), f: fn(canonical_source) { bind_outcome( o: target_serialize_source_from_model( - target: canonical_source_target, - emitted: original_ir.tree + target: target_model_to_bundle(target: canonical_source_target), + emitted: resolved_tree_to_node(tree: original_ir.tree) ), f: fn(canonical_source_again) { bind_outcome( o: parse_dag_source_ast_with_model( - source: canonical_source, + source: target_source_to_string(source: canonical_source), compilation_unit: source_authority_port, lm: lm ), @@ -451,8 +479,8 @@ fn source_authority_round_trip_with_model( bind_outcome( o: canonical_dag_source_emission_law_from_parts( original_ast: original_ast, - canonical_source_first: canonical_source, - canonical_source_second: canonical_source_again, + canonical_source_first: target_source_to_string(source: canonical_source), + canonical_source_second: target_source_to_string(source: canonical_source_again), reparsed_ast: reparsed_ast ), f: fn(canonical_source_law_witness) { @@ -462,7 +490,7 @@ fn source_authority_round_trip_with_model( Holds { value: canonical_source_law } => source_authority_law_from_parts( original_ast: original_ast, - canonical_source: canonical_source, + canonical_source: target_source_to_string(source: canonical_source), reparsed_ast: reparsed_ast, original_ir: original_ir, reparsed_ir: reparsed_ir, @@ -487,7 +515,7 @@ fn source_authority_round_trip_with_model( fn canonical_dag_source_parse_print_law( - source: DagSource, + source: String, canonical_source_target: TargetModel ) -> Outcome> { bind_outcome( @@ -501,23 +529,23 @@ fn canonical_dag_source_parse_print_law( f: fn(original_ir) { bind_outcome( o: target_serialize_source_from_model( - target: canonical_source_target, - emitted: original_ir.tree + target: target_model_to_bundle(target: canonical_source_target), + emitted: resolved_tree_to_node(tree: original_ir.tree) ), f: fn(canonical_source) { bind_outcome( o: target_serialize_source_from_model( - target: canonical_source_target, - emitted: original_ir.tree + target: target_model_to_bundle(target: canonical_source_target), + emitted: resolved_tree_to_node(tree: original_ir.tree) ), f: fn(canonical_source_again) { bind_outcome( - o: parse_dag_source_ast(source: canonical_source), + o: parse_dag_source_ast(source: target_source_to_string(source: canonical_source)), f: fn(reparsed_ast) { canonical_dag_source_emission_law_from_parts( original_ast: original_ast, - canonical_source_first: canonical_source, - canonical_source_second: canonical_source_again, + canonical_source_first: target_source_to_string(source: canonical_source), + canonical_source_second: target_source_to_string(source: canonical_source_again), reparsed_ast: reparsed_ast ) } @@ -534,7 +562,7 @@ fn canonical_dag_source_parse_print_law( fn source_authority_round_trip( - source: DagSource, + source: String, canonical_source_target: TargetModel ) -> Outcome> { source_authority_round_trip_with_model( diff --git a/src/v4/extdeps/formats/sql.dag b/src/v4/extdeps/formats/sql.dag index be5f04e5836..3fe5d7b0b1a 100644 --- a/src/v4/extdeps/formats/sql.dag +++ b/src/v4/extdeps/formats/sql.dag @@ -7,7 +7,7 @@ module v4.extdeps.formats.sql import v4.std.grammar { GrammarSchema } -import v4.std.algebra { fold_list, list_append } +import v4.std.algebra { Empty, fold_list, list_append } import v4.std.collection { List, Map, Optional } import v4.std.nat { Nat } import v4.std.cardinality { NonZeroNat } diff --git a/src/v4/extdeps/formatters/black.dag b/src/v4/extdeps/formatters/black.dag index 738b05f7213..0620646f51c 100644 --- a/src/v4/extdeps/formatters/black.dag +++ b/src/v4/extdeps/formatters/black.dag @@ -99,7 +99,7 @@ data black_defaults: BlackConfig = BlackConfig { type BlackConfigPatch = ConfigPatchRecord -fn black_layer(base: BlackConfig, patch: BlackConfigPatch) -> BlackConfig { +fn black_layer(base: BlackConfig, patch: ConfigPatchRecord) -> BlackConfig { config_patch_layer(base: base, patch: patch) } diff --git a/src/v4/extdeps/formatters/clang_format.dag b/src/v4/extdeps/formatters/clang_format.dag index 773104a9640..3157f2e9b54 100644 --- a/src/v4/extdeps/formatters/clang_format.dag +++ b/src/v4/extdeps/formatters/clang_format.dag @@ -1038,6 +1038,6 @@ data clang_format_defaults: ClangFormatConfig = ClangFormatConfig { type ClangFormatConfigPatch = ConfigPatchRecord -fn clang_format_layer(base: ClangFormatConfig, patch: ClangFormatConfigPatch) -> ClangFormatConfig { +fn clang_format_layer(base: ClangFormatConfig, patch: ConfigPatchRecord) -> ClangFormatConfig { config_patch_layer(base: base, patch: patch) } diff --git a/src/v4/extdeps/formatters/gofmt.dag b/src/v4/extdeps/formatters/gofmt.dag index 968bfffd7c1..43c48eea7ad 100644 --- a/src/v4/extdeps/formatters/gofmt.dag +++ b/src/v4/extdeps/formatters/gofmt.dag @@ -16,6 +16,6 @@ data gofmt_defaults: GofmtConfig = GofmtConfig {} type GofmtConfigPatch = ConfigPatchRecord -fn gofmt_layer(base: GofmtConfig, patch: GofmtConfigPatch) -> GofmtConfig { +fn gofmt_layer(base: GofmtConfig, patch: ConfigPatchRecord) -> GofmtConfig { config_patch_layer(base: base, patch: patch) } diff --git a/src/v4/extdeps/formatters/google_java_format.dag b/src/v4/extdeps/formatters/google_java_format.dag index d95b04df794..09698484a3a 100644 --- a/src/v4/extdeps/formatters/google_java_format.dag +++ b/src/v4/extdeps/formatters/google_java_format.dag @@ -27,6 +27,6 @@ data google_java_format_defaults: GoogleJavaFormatConfig = GoogleJavaFormatConfi type GoogleJavaFormatConfigPatch = ConfigPatchRecord -fn google_java_format_layer(base: GoogleJavaFormatConfig, patch: GoogleJavaFormatConfigPatch) -> GoogleJavaFormatConfig { +fn google_java_format_layer(base: GoogleJavaFormatConfig, patch: ConfigPatchRecord) -> GoogleJavaFormatConfig { config_patch_layer(base: base, patch: patch) } diff --git a/src/v4/extdeps/formatters/ktfmt.dag b/src/v4/extdeps/formatters/ktfmt.dag index def55ea5a99..312f3a6a49a 100644 --- a/src/v4/extdeps/formatters/ktfmt.dag +++ b/src/v4/extdeps/formatters/ktfmt.dag @@ -92,6 +92,6 @@ data ktfmt_defaults: KtfmtConfig = KtfmtConfig { type KtfmtConfigPatch = ConfigPatchRecord -fn ktfmt_layer(base: KtfmtConfig, patch: KtfmtConfigPatch) -> KtfmtConfig { +fn ktfmt_layer(base: KtfmtConfig, patch: ConfigPatchRecord) -> KtfmtConfig { config_patch_layer(base: base, patch: patch) } diff --git a/src/v4/extdeps/formatters/lean4_format.dag b/src/v4/extdeps/formatters/lean4_format.dag index 9a09241f28d..d632318806d 100644 --- a/src/v4/extdeps/formatters/lean4_format.dag +++ b/src/v4/extdeps/formatters/lean4_format.dag @@ -217,6 +217,6 @@ data lean4_format_defaults: Lean4FormatConfig = Lean4FormatConfig { type Lean4FormatConfigPatch = ConfigPatchRecord -fn lean4_format_layer(base: Lean4FormatConfig, patch: Lean4FormatConfigPatch) -> Lean4FormatConfig { +fn lean4_format_layer(base: Lean4FormatConfig, patch: ConfigPatchRecord) -> Lean4FormatConfig { config_patch_layer(base: base, patch: patch) } diff --git a/src/v4/extdeps/formatters/prettier.dag b/src/v4/extdeps/formatters/prettier.dag index ae295c35ecf..cce13fadb72 100644 --- a/src/v4/extdeps/formatters/prettier.dag +++ b/src/v4/extdeps/formatters/prettier.dag @@ -209,14 +209,14 @@ data prettier_defaults: PrettierConfig = PrettierConfig { type PrettierFormattingOptionsPatch = ConfigPatchRecord -fn apply_prettier_formatting_options_patch(base: PrettierFormattingOptions, patch: PrettierFormattingOptionsPatch) -> PrettierFormattingOptions { +fn apply_prettier_formatting_options_patch(base: PrettierFormattingOptions, patch: ConfigPatchRecord) -> PrettierFormattingOptions { config_patch_layer(base: base, patch: patch) } // 🟡 gated — feature:prettier-nested-config-patch — bind T-4.16 follow-on — dissolve-on-arrival: model `options` as `FieldPatch` (or nested patch substrate) so `PrettierConfigPatch = ConfigPatchRecord`; until then hand `prettier_layer` composes nested `PrettierFormattingOptionsPatch` + scalar `overrides`. type PrettierConfigPatch { - options: PrettierFormattingOptionsPatch + options: ConfigPatchRecord overrides: FieldPatch> } diff --git a/src/v4/extdeps/formatters/rustfmt.dag b/src/v4/extdeps/formatters/rustfmt.dag index 8360eb16c52..ba66c9bced6 100644 --- a/src/v4/extdeps/formatters/rustfmt.dag +++ b/src/v4/extdeps/formatters/rustfmt.dag @@ -340,6 +340,6 @@ data rustfmt_defaults: RustfmtConfig = RustfmtConfig { type RustfmtConfigPatch = ConfigPatchRecord -fn rustfmt_layer(base: RustfmtConfig, patch: RustfmtConfigPatch) -> RustfmtConfig { +fn rustfmt_layer(base: RustfmtConfig, patch: ConfigPatchRecord) -> RustfmtConfig { config_patch_layer(base: base, patch: patch) } diff --git a/src/v4/extdeps/formatters/swift_format.dag b/src/v4/extdeps/formatters/swift_format.dag index db0e253aa19..e65ddb0d5a7 100644 --- a/src/v4/extdeps/formatters/swift_format.dag +++ b/src/v4/extdeps/formatters/swift_format.dag @@ -125,6 +125,6 @@ data swift_format_defaults: SwiftFormatConfig = SwiftFormatConfig { type SwiftFormatConfigPatch = ConfigPatchRecord -fn swift_format_layer(base: SwiftFormatConfig, patch: SwiftFormatConfigPatch) -> SwiftFormatConfig { +fn swift_format_layer(base: SwiftFormatConfig, patch: ConfigPatchRecord) -> SwiftFormatConfig { config_patch_layer(base: base, patch: patch) } diff --git a/src/v4/extdeps/languages/ecmascript.dag b/src/v4/extdeps/languages/ecmascript.dag index e284b915a3a..29e4492cac3 100644 --- a/src/v4/extdeps/languages/ecmascript.dag +++ b/src/v4/extdeps/languages/ecmascript.dag @@ -18,7 +18,7 @@ module v4.extdeps.languages.ecmascript -import v4.std.algebra { Empty, fold_list, list_append, list_snoc_item } +import v4.std.algebra { Empty, FreeMonoid, fold_list, list_append, list_snoc_item } import v4.std.grammar { ParseGrammar, GrammarExpr, @@ -968,7 +968,7 @@ type EcmascriptFormalAltChoiceState = EcmascriptFormalAltChoiceUninitialized | EcmascriptFormalAltChoiceReady { expr: GrammarExpr } -fn ecmascript_formal_alternatives_to_choice_expr(alts: List>) -> GrammarExpr { +fn ecmascript_formal_alternatives_to_choice_expr(alts: FreeMonoid>) -> GrammarExpr { match fold_list( xs: alts, empty: EcmascriptFormalAltChoiceUninitialized, @@ -989,20 +989,20 @@ fn ecmascript_formal_alternatives_to_choice_expr(alts: List List> { +fn ecmascript_formal_rhs_alternatives_accum_empty() -> FreeMonoid> { Empty } fn ecmascript_formal_collect_rhs_alternative( - acc: List>, + acc: FreeMonoid>, prod: FormalProduction -) -> List> { +) -> FreeMonoid> { list_snoc_item(xs: acc, item: prod.rhs) } fn ecmascript_formal_rhs_alternatives_from_productions( prods: List -) -> List> { +) -> FreeMonoid> { fold_list( xs: prods, empty: ecmascript_formal_rhs_alternatives_accum_empty(), diff --git a/src/v4/extdeps/languages/go.dag b/src/v4/extdeps/languages/go.dag index afd9bdb20a6..77442f33b7b 100644 --- a/src/v4/extdeps/languages/go.dag +++ b/src/v4/extdeps/languages/go.dag @@ -71,6 +71,7 @@ import v4.std.target_model { TargetAtomRealization, TargetAtomTypeShape, TargetModel, + TargetModelBundle, TargetTypeExpression, ValueBoolLiteral, ValueCharUnicodeScalar, @@ -1804,8 +1805,8 @@ fn go_mvp1_target_model_node() -> Node { } } -fn go_mvp1_target_model() -> TargetModel { - TargetModel { +fn go_mvp1_target_model() -> TargetModelBundle { + TargetModelBundle { bundle: go_mvp1_target_model_node(), lex: go_wave1_lex(), binding_spellings: go_mvp1_binding_spellings(), diff --git a/src/v4/extdeps/languages/java.dag b/src/v4/extdeps/languages/java.dag index 060b6309b09..a98a6a64656 100644 --- a/src/v4/extdeps/languages/java.dag +++ b/src/v4/extdeps/languages/java.dag @@ -96,6 +96,8 @@ import v4.std.node { import v4.std.logic { Bool, bool_boolean_algebra } import v4.std.algebra { BooleanAlgebra, + Cons, + Empty, boolean_algebra_node, boolean_algebra_type_node, commutative_semiring_node, diff --git a/src/v4/extdeps/languages/llvm_ir.dag b/src/v4/extdeps/languages/llvm_ir.dag index 5820717b34d..5aea53f4e4d 100644 --- a/src/v4/extdeps/languages/llvm_ir.dag +++ b/src/v4/extdeps/languages/llvm_ir.dag @@ -43,7 +43,7 @@ import v4.std.lexing { TriviaRule, WhitespaceChar } -import v4.std.algebra { fold_list, list_append, list_snoc_item } +import v4.std.algebra { Empty, fold_list, list_append, list_snoc_item } import v4.std.cardinality { NonZeroNat } import v4.std.collection { List, Map } import v4.std.model_core { diff --git a/src/v4/extdeps/languages/machine_code.dag b/src/v4/extdeps/languages/machine_code.dag index 077bf3cee8e..248b6bbcca4 100644 --- a/src/v4/extdeps/languages/machine_code.dag +++ b/src/v4/extdeps/languages/machine_code.dag @@ -19,7 +19,7 @@ import v4.std.lexing { TriviaRule, WhitespaceChar } -import v4.std.algebra { fold_list, list_snoc_item } +import v4.std.algebra { Empty, fold_list, list_snoc_item } import v4.std.collection { List, Map } import v4.std.machine { Byte } import v4.std.text { String } diff --git a/src/v4/extdeps/languages/python.dag b/src/v4/extdeps/languages/python.dag index 1861d4d59b9..c7c50a44b70 100644 --- a/src/v4/extdeps/languages/python.dag +++ b/src/v4/extdeps/languages/python.dag @@ -9,7 +9,7 @@ module v4.extdeps.languages.python -import v4.std.algebra { Empty, fold_list, list_append, list_snoc_item } +import v4.std.algebra { Empty, FreeMonoid, fold_list, list_append, list_snoc_item } import v4.std.grammar { ParseGrammar, GrammarExpr, @@ -1110,7 +1110,7 @@ type PythonFormalAltChoiceState = PythonFormalAltChoiceUninitialized | PythonFormalAltChoiceReady { expr: GrammarExpr } -fn python_formal_alternatives_to_choice_expr(alts: List>) -> GrammarExpr { +fn python_formal_alternatives_to_choice_expr(alts: FreeMonoid>) -> GrammarExpr { match fold_list( xs: alts, empty: PythonFormalAltChoiceUninitialized, @@ -1131,20 +1131,20 @@ fn python_formal_alternatives_to_choice_expr(alts: List List> { +fn python_formal_rhs_alternatives_accum_empty() -> FreeMonoid> { Empty } fn python_formal_collect_rhs_alternative( - acc: List>, + acc: FreeMonoid>, prod: FormalProduction -) -> List> { +) -> FreeMonoid> { list_snoc_item(xs: acc, item: prod.rhs) } fn python_formal_rhs_alternatives_from_productions( prods: List -) -> List> { +) -> FreeMonoid> { fold_list( xs: prods, empty: python_formal_rhs_alternatives_accum_empty(), diff --git a/src/v4/extdeps/languages/rust.dag b/src/v4/extdeps/languages/rust.dag index 99ae7e37e94..eeeb32f6837 100644 --- a/src/v4/extdeps/languages/rust.dag +++ b/src/v4/extdeps/languages/rust.dag @@ -93,6 +93,7 @@ import v4.std.target_model { TargetFunctionTypeShape, TargetGenericApply, TargetModel, + TargetModelBundle, TargetSumTypeShape, TargetTypeExpressionProjection, ValueBoolLiteral, @@ -1688,8 +1689,8 @@ fn rust_mvp1_target_model_node() -> Node { } } -fn rust_mvp1_target_model() -> TargetModel { - TargetModel { +fn rust_mvp1_target_model() -> TargetModelBundle { + TargetModelBundle { bundle: rust_mvp1_target_model_node(), lex: rust_wave1_lex(), binding_spellings: rust_mvp1_binding_spellings(), @@ -2421,7 +2422,7 @@ fn rust_snoc_primitive_bundle( Accepted { value: bundles, diagnostics: _ } => match primitive_fact_bundle_for_subject( registry: registry, subject_carrier: subject_carrier, - target: rust_mvp1_target_model() + target: rust_mvp1_target_model_staging() ) { Accepted { value: bundle, diagnostics: d } => Accepted { @@ -3527,8 +3528,8 @@ fn rust_sg2_serialize_source_node() -> Node { } } -fn rust_sg2_type_expr_target_model() -> TargetModel { - TargetModel { +fn rust_sg2_type_expr_target_model() -> TargetModelBundle { + TargetModelBundle { bundle: rust_sg2_type_expr_target_model_node(), lex: ModeledLexRules { root: rust_sg2_wave1_lex_rules() }, binding_spellings: rust_sg2_binding_spellings(), diff --git a/src/v4/extdeps/languages/typescript.dag b/src/v4/extdeps/languages/typescript.dag index c35b8357449..a079848fba1 100644 --- a/src/v4/extdeps/languages/typescript.dag +++ b/src/v4/extdeps/languages/typescript.dag @@ -107,7 +107,7 @@ import v4.std.grounding { } import v4.std.node_query { find_named_child } import v4.std.target_model { ConcreteSyntaxToken, FixedToken, BoundToken, concrete_syntax_token_class, concrete_syntax_token_to_node } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.std.target_model { TargetAtomRealization, TargetAtomTypeShape, @@ -1685,8 +1685,8 @@ fn ts_sg2_binding_spellings() -> Map { ) } -fn ts_sg2_type_expr_target_model() -> TargetModel { - TargetModel { +fn ts_sg2_type_expr_target_model() -> TargetModelBundle { + TargetModelBundle { bundle: ts_sg2_type_expr_target_model_node(), lex: ts_sg2_type_expr_lex(), binding_spellings: ts_sg2_binding_spellings(), diff --git a/src/v4/lens/affected_set.dag b/src/v4/lens/affected_set.dag index 91489139d56..17844f86d6f 100644 --- a/src/v4/lens/affected_set.dag +++ b/src/v4/lens/affected_set.dag @@ -42,9 +42,6 @@ import v4.lens.application { AncestorFrame, AncestorWalk, collect_ancestor_frame // RULING-1: 🟢 pretty-much-done — node alias. -type Dag = Node - - // RULING-1: 🟢 pretty-much-done — dimension identity. type AffectedDimension = Symbol @@ -150,14 +147,14 @@ type FrontierReceipt // RULING-1: 🟡 needs-more-work — frontier read. type AffectedFrontierRead { - proven_transitive_dependency_frontier: fn(Dag, EditDimension) -> FrontierReceipt + proven_transitive_dependency_frontier: fn(Node, EditDimension) -> FrontierReceipt } // RULING-1: 🟡 needs-more-work — boundary read. type AffectedBoundaryRead { - boundary_hash_receipt: fn(Dag, Path, Node) -> HashReceipt, - changed_dimension_receipt: fn(Dag, Edit) -> ChangedDimensionReceipt + boundary_hash_receipt: fn(Node, Path, Node) -> HashReceipt, + changed_dimension_receipt: fn(Node, Edit) -> ChangedDimensionReceipt } @@ -165,7 +162,7 @@ type AffectedBoundaryRead { type AffectedSetRead { boundary: AffectedBoundaryRead frontier: AffectedFrontierRead, - propagation_receipt: fn(Dag, EditDimension, DependencyView) -> PropagationReceipt + propagation_receipt: fn(Node, EditDimension, DependencyView) -> PropagationReceipt } @@ -177,7 +174,7 @@ type AffectedPostEditDagRead { // RULING-1: 🟢 pretty-much-done — fold state. type AffectedFoldAcc { - dag: Dag + dag: Node frontier: ReExecFrontier pending: Diagnostics } @@ -186,7 +183,7 @@ type AffectedFoldAcc { // 🟢 coproduct dissolution — Wave-2-A affected-set fold state. type AffectedSetFoldAcc = AffectedSetActive { - dag: Dag, + dag: Node, changes: ChangeSet, affected: List, exclusions: List @@ -228,7 +225,7 @@ fn empty_frontier() -> ReExecFrontier { } -fn empty_affected_fold_acc(dag: Dag) -> AffectedFoldAcc { +fn empty_affected_fold_acc(dag: Node) -> AffectedFoldAcc { AffectedFoldAcc { dag: dag, frontier: empty_frontier(), @@ -237,7 +234,7 @@ fn empty_affected_fold_acc(dag: Dag) -> AffectedFoldAcc { } -fn empty_affected_set_fold_acc(dag: Dag) -> AffectedSetFoldAcc { +fn empty_affected_set_fold_acc(dag: Node) -> AffectedSetFoldAcc { AffectedSetActive { dag: dag, changes: ChangeSet { changes: [] }, @@ -670,7 +667,7 @@ fn mark_whole_dag_diagnostic(diagnostic: Diagnostic) -> ReExecFrontier { } -fn boundary_receipt(read_model: AffectedSetRead, dag: Dag, path: Path, replacement: Node) -> BoundaryReceipt { +fn boundary_receipt(read_model: AffectedSetRead, dag: Node, path: Path, replacement: Node) -> BoundaryReceipt { match read_model.boundary.boundary_hash_receipt(dag, path, replacement) { HashUnchangedPure { content_hash: h } => BoundaryPruned { @@ -686,7 +683,7 @@ fn boundary_receipt(read_model: AffectedSetRead, dag: Dag, path: Path, replaceme fn frontier_receipt( read_model: AffectedSetRead, - dag: Dag, + dag: Node, edit: Edit, dimension: AffectedDimension ) -> FrontierReceipt { @@ -699,7 +696,7 @@ fn frontier_receipt( fn propagation_receipt( read_model: AffectedSetRead, - dag: Dag, + dag: Node, edit: Edit, dimension: AffectedDimension, dependency: DependencyView @@ -714,7 +711,7 @@ fn propagation_receipt( fn expand_dimension( read_model: AffectedSetRead, - dag: Dag, + dag: Node, frontier: ReExecFrontier, edit: Edit, dimension: AffectedDimension @@ -755,7 +752,7 @@ fn expand_dimension( fn seed_edit_fold_acc_live( read_model: AffectedSetRead, - post_edit_dag: fn(Dag, Edit) -> AffectedPostEditDagRead, + post_edit_dag: fn(Node, Edit) -> AffectedPostEditDagRead, acc: AffectedFoldAcc, edit: Edit ) -> AffectedFoldAcc { @@ -813,8 +810,8 @@ fn seed_edit_fold_acc_live( fn expand_changed_dimensions( read_model: AffectedSetRead, - boundary_dag: Dag, - frontier_dag: Dag, + boundary_dag: Node, + frontier_dag: Node, frontier: ReExecFrontier, edit: Edit ) -> ReExecFrontier { @@ -843,7 +840,7 @@ fn expand_changed_dimensions( fn seed_edit_fold_acc( read_model: AffectedSetRead, - post_edit_dag: fn(Dag, Edit) -> AffectedPostEditDagRead, + post_edit_dag: fn(Node, Edit) -> AffectedPostEditDagRead, acc: AffectedFoldAcc, edit: Edit ) -> AffectedFoldAcc { @@ -862,7 +859,7 @@ fn seed_edit_fold_acc( fn expand_affected_dimension( read_model: AffectedSetRead, - dag: Dag, + dag: Node, acc: AffectedSetFoldAcc, edit: Edit, dimension: AffectedDimension @@ -908,8 +905,8 @@ fn expand_affected_dimension( fn expand_affected_dimensions( read_model: AffectedSetRead, - boundary_dag: Dag, - frontier_dag: Dag, + boundary_dag: Node, + frontier_dag: Node, acc: AffectedSetFoldAcc, edit: Edit ) -> AffectedSetFoldAcc { @@ -938,7 +935,7 @@ fn expand_affected_dimensions( fn seed_affected_set_fold_acc_live( read_model: AffectedSetRead, - post_edit_dag: fn(Dag, Edit) -> AffectedPostEditDagRead, + post_edit_dag: fn(Node, Edit) -> AffectedPostEditDagRead, acc: AffectedSetFoldAcc, edit: Edit ) -> AffectedSetFoldAcc { @@ -1021,8 +1018,8 @@ fn seed_affected_set_fold_acc_live( fn affected_set_from_diff( read_model: AffectedSetRead, - post_edit_dag: fn(Dag, Edit) -> AffectedPostEditDagRead, - dag: Dag, + post_edit_dag: fn(Node, Edit) -> AffectedPostEditDagRead, + dag: Node, diff: Diff ) -> Witness { Holds { @@ -1043,8 +1040,8 @@ fn affected_set_from_diff( // IRT-1 canonical entry: pure fold over diff.edits — O(changed-region), fail-closed on unknown receipts. fn re_exec_frontier_from_diff( read_model: AffectedSetRead, - post_edit_dag: fn(Dag, Edit) -> AffectedPostEditDagRead, - dag: Dag, + post_edit_dag: fn(Node, Edit) -> AffectedPostEditDagRead, + dag: Node, diff: Diff ) -> Witness { Holds { @@ -1080,7 +1077,7 @@ fn canonical_boundary_exclusion_receipt(node: Node, h: Hash) -> BoundaryReceipt } -fn canonical_boundary_hash_receipt(dag: Dag, path: Path, replacement: Node) -> HashReceipt { +fn canonical_boundary_hash_receipt(dag: Node, path: Path, replacement: Node) -> HashReceipt { match subterm_at(root: dag, p: path) { Accepted { value: current, diagnostics: _ } => if content_hash(n: current) == content_hash(n: replacement) { @@ -1102,7 +1099,7 @@ fn canonical_boundary_hash_receipt(dag: Dag, path: Path, replacement: Node) -> H // 🟡 canonical-read scaffold — feature:affected-set-dimension-delta-receipt-carrier — bind T-21/T-24 — dissolve-on: per-edit dimension delta generation produces ChangedDimensions. -fn canonical_changed_dimension_receipt(dag: Dag, edit: Edit) -> ChangedDimensionReceipt { +fn canonical_changed_dimension_receipt(dag: Node, edit: Edit) -> ChangedDimensionReceipt { ChangedDimensionsUnknown { reason: ^affected_set_reason_changed_dimension_unresolved } } @@ -1181,7 +1178,7 @@ fn canonical_ancestor_dependencies(frames: List) -> FrontierRecei } -fn canonical_region_dependencies(dag: Dag, walk: AncestorWalk) -> FrontierReceipt { +fn canonical_region_dependencies(dag: Node, walk: AncestorWalk) -> FrontierReceipt { match canonical_ancestor_dependencies(frames: walk.frames) { FrontierProduced { dependencies: _ } => let closure = affected_set_closure(dependencies: dependency_lens(root: dag), edit_locus: walk.current) @@ -1196,7 +1193,7 @@ fn canonical_region_dependencies(dag: Dag, walk: AncestorWalk) -> FrontierReceip } -fn canonical_transitive_frontier(dag: Dag, edit_dimension: EditDimension) -> FrontierReceipt { +fn canonical_transitive_frontier(dag: Node, edit_dimension: EditDimension) -> FrontierReceipt { match collect_ancestor_frames(root: dag, steps: edit_dimension.edit.at.steps) { Accepted { value: walk, diagnostics: _ } => canonical_region_dependencies(dag: dag, walk: walk) @@ -1207,7 +1204,7 @@ fn canonical_transitive_frontier(dag: Dag, edit_dimension: EditDimension) -> Fro fn canonical_propagation_receipt( - dag: Dag, + dag: Node, edit_dimension: EditDimension, dependency: DependencyView ) -> PropagationReceipt { @@ -1247,14 +1244,14 @@ fn canonical_affected_set_read() -> AffectedSetRead { } -fn canonical_post_edit_dag(dag: Dag, edit: Edit) -> AffectedPostEditDagRead { +fn canonical_post_edit_dag(dag: Node, edit: Edit) -> AffectedPostEditDagRead { AffectedPostEditDagRead { outcome: substitute_at(root: dag, path: edit.at, replacement: edit.replacement) } } -fn affected_set(dag: Dag, diff: Diff) -> Witness { +fn affected_set(dag: Node, diff: Diff) -> Witness { re_exec_frontier_from_diff( read_model: canonical_affected_set_read(), post_edit_dag: canonical_post_edit_dag, diff --git a/src/v4/lens/affected_set_examples.dag b/src/v4/lens/affected_set_examples.dag index 52949917700..c532d8e1c3b 100644 --- a/src/v4/lens/affected_set_examples.dag +++ b/src/v4/lens/affected_set_examples.dag @@ -22,7 +22,6 @@ import v4.lens.affected_set { AffectedSetRead, ChangedDimensions, ChangedDimensionReceipt, - Dag, EditDimension, FrontierProduced, FrontierReceipt, @@ -137,12 +136,12 @@ data expected_affected_set_whole_dag_absorbs_later_unknown: ReExecFrontier = Fai } -fn affected_set_example_boundary_hash_receipt(dag: Dag, path: Path, replacement: Node) -> HashReceipt { +fn affected_set_example_boundary_hash_receipt(dag: Node, path: Path, replacement: Node) -> HashReceipt { HashChanged } -fn affected_set_example_changed_dimension_receipt(dag: Dag, edit: Edit) -> ChangedDimensionReceipt { +fn affected_set_example_changed_dimension_receipt(dag: Node, edit: Edit) -> ChangedDimensionReceipt { ChangedDimensions { first: ^affected_set_example_dimension, rest: [] @@ -150,13 +149,13 @@ fn affected_set_example_changed_dimension_receipt(dag: Dag, edit: Edit) -> Chang } -fn affected_set_example_transitive_frontier(dag: Dag, edit_dimension: EditDimension) -> FrontierReceipt { +fn affected_set_example_transitive_frontier(dag: Node, edit_dimension: EditDimension) -> FrontierReceipt { FrontierProduced { dependencies: [] } } fn affected_set_example_propagation_receipt( - dag: Dag, + dag: Node, edit_dimension: EditDimension, dependency: DependencyView ) -> PropagationReceipt { @@ -176,14 +175,14 @@ data affected_set_example_read: AffectedSetRead = AffectedSetRead { } -fn affected_set_example_post_edit_accepts(dag: Dag, edit: Edit) -> AffectedPostEditDagRead { +fn affected_set_example_post_edit_accepts(dag: Node, edit: Edit) -> AffectedPostEditDagRead { AffectedPostEditDagRead { outcome: Accepted { value: dag, diagnostics: None } } } -fn affected_set_example_post_edit_rejects(dag: Dag, edit: Edit) -> AffectedPostEditDagRead { +fn affected_set_example_post_edit_rejects(dag: Node, edit: Edit) -> AffectedPostEditDagRead { AffectedPostEditDagRead { outcome: Rejected { diagnostics: diagnostics_singleton(d: affected_set_example_invalid_edit_diagnostic) diff --git a/src/v4/lens/coverage.dag b/src/v4/lens/coverage.dag index 66ac936c972..5d434d49ad6 100644 --- a/src/v4/lens/coverage.dag +++ b/src/v4/lens/coverage.dag @@ -46,6 +46,7 @@ import v4.std.diagnostic { Accepted, Diagnostic, NonEmptyDiagnostics, + None, Rejected, Outcome, Textual, @@ -291,7 +292,7 @@ fn l6_coverage_key_eq(a: L6CoverageKey, b: L6CoverageKey) -> Bool { type_construction_subject_eq(a: a.subject, b: b.subject) } -fn l7_coverage_key_eq(a: L7CoverageKey, b: L7CoverageKey) -> Bool { +fn l7_coverage_key_eq(a: AlgebraLawSubject, b: AlgebraLawSubject) -> Bool { algebra_law_subject_eq(a: a, b: b) } diff --git a/src/v4/lens/structural_resolution.dag b/src/v4/lens/structural_resolution.dag index 1f605b773eb..a57e87498b2 100644 --- a/src/v4/lens/structural_resolution.dag +++ b/src/v4/lens/structural_resolution.dag @@ -16,7 +16,7 @@ import v4.compiler.infer { InferredTree, infer_facts_lookup_miss } -import v4.std.algebra { bag_eq, list_snoc_item } +import v4.std.algebra { Cons, Empty, FreeMonoid, list_snoc_item } import v4.compiler.resolve { resolve_reason_unbound_symbol } @@ -31,6 +31,7 @@ import v4.std.dependency { } import v4.std.logic { Bool } import v4.std.node { Node } +import v4.std.diagnostic { Diagnostic } import v4.std.witness { Holds, Violates, Witness } // 🟢 projection carrier — Practice 11: binding status is computed from @@ -134,9 +135,23 @@ fn structural_resolution_fact( dependencies: List ) -> StructuralResolutionFact { StructuralResolutionFact { - dependencies: fold(dependencies, init: [], f: fn(acc, view) { - list_snoc_item(xs: acc, item: structural_resolution_classify(tree: tree, view: view)) - }) + dependencies: structural_resolution_classify_all(tree: tree, dependencies: dependencies, acc: Empty) + } +} + +fn structural_resolution_classify_all( + tree: InferredTree, + dependencies: FreeMonoid, + acc: FreeMonoid>, +) -> FreeMonoid> { + match dependencies { + Empty => acc + Cons { head: view, tail: rest } => + structural_resolution_classify_all( + tree: tree, + dependencies: rest, + acc: list_snoc_item(xs: acc, item: structural_resolution_classify(tree: tree, view: view)) + ) } } @@ -195,5 +210,21 @@ fn structural_resolution_classified_eq( // dissolve-on-arrival: T-13 lens driver / generated TestClaim supplies canonical // equality or content_hash for lens facts; multiset compare is compile-only until B2. fn fact_eq(a: StructuralResolutionFact, b: StructuralResolutionFact) -> Bool { - bag_eq(xs: a.dependencies, ys: b.dependencies, eq: structural_resolution_classified_eq) + structural_resolution_classified_list_eq(left: a.dependencies, right: b.dependencies) +} + +fn structural_resolution_classified_list_eq( + left: FreeMonoid>, + right: FreeMonoid>, +) -> Bool { + match left { + Empty => match right { Empty => true Cons { head: _, tail: _ } => false } + Cons { head: left_head, tail: left_tail } => + match right { + Empty => false + Cons { head: right_head, tail: right_tail } => + structural_resolution_classified_eq(a: left_head, b: right_head) && + structural_resolution_classified_list_eq(left: left_tail, right: right_tail) + } + } } diff --git a/src/v4/std/artifact.dag b/src/v4/std/artifact.dag index be867937f61..6fd744e4af4 100644 --- a/src/v4/std/artifact.dag +++ b/src/v4/std/artifact.dag @@ -76,7 +76,7 @@ fn make_generated_artifact(base: Artifact, at: Locus) -> Outcome GeneratedArtifact { +fn test_claim_generated_artifact(id: GeneratorId, file_path: String) -> GeneratedArtifact { GeneratedArtifact { refined: Refined { base: Artifact { kind: TestClaimArtifact, id: id, file_path: file_path } diff --git a/src/v4/std/dependency.dag b/src/v4/std/dependency.dag index 355a736dc7a..697efd8bca6 100644 --- a/src/v4/std/dependency.dag +++ b/src/v4/std/dependency.dag @@ -4,7 +4,7 @@ module v4.std.dependency -import v4.std.algebra { list_append, list_snoc_item } +import v4.std.algebra { list_append } import v4.std.collection { List } import v4.std.logic { Bool } import v4.std.node { @@ -159,6 +159,10 @@ fn append_dependency_views(left: List, right: List List { + [view] +} + fn dependency_fold_init(n: Node) -> DependencyFoldState { DependencyFoldState { current: n, @@ -170,7 +174,10 @@ fn dependency_fold_step(acc: DependencyFoldState, edge: Edge, child_state: Depen DependencyFoldState { current: acc.current, dependencies: append_dependency_views( - left: list_snoc_item(xs: acc.dependencies, item: dependency_view_for_edge(parent: acc.current, edge: edge)), + left: append_dependency_views( + left: acc.dependencies, + right: dependency_view_singleton(view: dependency_view_for_edge(parent: acc.current, edge: edge)) + ), right: child_state.dependencies ) } diff --git a/src/v4/std/diagnostic.dag b/src/v4/std/diagnostic.dag index 9f04d88fefa..84d1b7c192b 100644 --- a/src/v4/std/diagnostic.dag +++ b/src/v4/std/diagnostic.dag @@ -7,8 +7,8 @@ module v4.std.diagnostic -import v4.std.algebra { bag_eq, list_append, Magma, Monoid, Semigroup, list_snoc_item } -import v4.std.node { Node } +import v4.std.algebra { Empty, bag_eq, list_append, Magma, Monoid, Semigroup, list_snoc_item } +import v4.std.node { Node, Symbol } // 🟢 coproduct dissolution — CP-3229-GREEN-TERMINAL. type Extent = WholeFile diff --git a/src/v4/std/lexing.dag b/src/v4/std/lexing.dag index e2762bfe7ec..4f000673667 100644 --- a/src/v4/std/lexing.dag +++ b/src/v4/std/lexing.dag @@ -81,7 +81,6 @@ fn lex_rule_token_class_member(rule: LexRule, token_class: Symbol) -> Bool { } } - fn lex_rule_set_token_class_member(rules: LexRuleSet, token_class: Symbol) -> Bool { fold_list( xs: rules.rules, diff --git a/src/v4/std/target_model.dag b/src/v4/std/target_model.dag index ea96eb123f6..1648fdfa6a8 100644 --- a/src/v4/std/target_model.dag +++ b/src/v4/std/target_model.dag @@ -38,14 +38,17 @@ import v4.std.diagnostic { Accepted, Diagnostic, ExternalContractUnknown, + None, Outcome, Rejected, Unavailable, + bind_outcome, diagnostics_merge, node_locus, bind_outcome, outcome_accepted, - outcome_rejected + outcome_rejected, + port_locus } import v4.std.lexing { LexRules, VoidLexRules } import v4.std.find_witness { diff --git a/src/v4/std/verification.dag b/src/v4/std/verification.dag index 69731560db6..e1b9f0951e6 100644 --- a/src/v4/std/verification.dag +++ b/src/v4/std/verification.dag @@ -8,7 +8,7 @@ module v4.std.verification import v4.std.algebra { Empty, any, fold_list, list_append, list_snoc_item } import v4.std.collection { List } import v4.std.logic { Bool } -import v4.std.node { Node, NodeFold, Symbol, fold_node } +import v4.std.node { Edge, Node, NodeFold, Symbol, fold_node } import v4.std.target_model { TargetModel } import v4.std.diagnostic { Accepted, @@ -16,6 +16,7 @@ import v4.std.diagnostic { Diagnostic, Extent, Locus, + None, NodeLocus, NonEmptyDiagnostics, PortLocus, diff --git a/src/v4/test/claim/complexity_gate/comprep_wave1_add_subject_producer.dag b/src/v4/test/claim/complexity_gate/comprep_wave1_add_subject_producer.dag index 956d87a8534..79739452098 100644 --- a/src/v4/test/claim/complexity_gate/comprep_wave1_add_subject_producer.dag +++ b/src/v4/test/claim/complexity_gate/comprep_wave1_add_subject_producer.dag @@ -28,6 +28,10 @@ import v4.std.node { Node, Symbol } data comprep_wave1_add_subject_source_file: Symbol = comprep_wave1_add_subject_source_file +fn comprep_wave1_add_parse_tree_to_node(tree: ParseTree) -> Node { + tree +} + fn comprep_wave1_add_parse_root() -> GrammarRoot { GrammarRoot { start: ^dag_production_mvp1_fn_add, @@ -66,7 +70,7 @@ fn comprep_source_resolved_add_arrow() -> Outcome { o: comprep_wave1_add_parse_tokens(tokens: tokens.tokens), f: fn(parsed) { bind_outcome( - o: normalize(parse_tree: parsed), + o: normalize(parse_tree: comprep_wave1_add_parse_tree_to_node(tree: parsed)), f: fn(normalized) { resolve(tree: normalized, lm: lm) } diff --git a/src/v4/test/claim/grounding_typescript/sg_claims.dag b/src/v4/test/claim/grounding_typescript/sg_claims.dag index ad660ad03ca..6f5fe736a63 100644 --- a/src/v4/test/claim/grounding_typescript/sg_claims.dag +++ b/src/v4/test/claim/grounding_typescript/sg_claims.dag @@ -23,9 +23,12 @@ import v4.extdeps.languages.typescript { ts_sg2_instantiation_source_type_node, ts_sg2_type_expr_target_model, ts_std_text_string_type_node, - ts_target_atom_realization_catalog, + ts_target_atom_realization_bool, + ts_target_atom_realization_string, + ts_target_atom_realization_symbol, ts_type_expression_projection } +import v4.std.collection { List } import v4.std.diagnostic { Accepted, Rejected } import v4.std.grounding { GroundingEvidenceSchema, @@ -37,6 +40,7 @@ import v4.std.logic { Bool, bool_node } import v4.std.node { Atom, Node, Symbol, TypeNode, content_hash, SyntheticOccurrence } import v4.std.runtime { RuntimeValue } import v4.std.target_model { + TargetAtomRealization, symbol_kernel_type_node, target_atom_realization_lookup_in_catalog, target_carrier_free_monoid_node, @@ -164,12 +168,20 @@ fn ts_g2_sg5_free_monoid_absence_evidence_targets_canonical_carrier() -> Bool { } } +fn ts_target_atom_realization_catalog_for_claim() -> List { + [ + ts_target_atom_realization_symbol, + ts_target_atom_realization_bool, + ts_target_atom_realization_string + ] +} + // 🟡 predicate dissolution — feature:T-22-outcome-to-bool-claim-bridge — bind TASKS.md T-22 / // G.2 grounding_typescript run_test_claim roster — dissolve-on: T-22 claim runner evaluates // Outcome and lookup results directly without Accepted=>true / Rejected=>false Bool projection. fn ts_g2_sg1_atom_lookup_accepts(source_carrier: Node) -> Bool { match target_atom_realization_lookup_in_catalog( - catalog: ts_target_atom_realization_catalog, + catalog: ts_target_atom_realization_catalog_for_claim(), source_carrier: source_carrier ) { Accepted { value: _, diagnostics: _ } => true diff --git a/src/v4/test/claim/lens_application/apply_lens_introspect_rejection_is_advisory.dag b/src/v4/test/claim/lens_application/apply_lens_introspect_rejection_is_advisory.dag index 5cf4187349e..d5a9b1fa83b 100644 --- a/src/v4/test/claim/lens_application/apply_lens_introspect_rejection_is_advisory.dag +++ b/src/v4/test/claim/lens_application/apply_lens_introspect_rejection_is_advisory.dag @@ -15,7 +15,7 @@ import v4.compiler.compile { compile_lens_gate_rejected_diagnostic } import v4.compiler.infer { InferredTree } -import v4.std.diagnostic { Accepted, Diagnostics, None, Outcome, PortLocus, Rejected, Some, outcome_rejected } +import v4.std.diagnostic { Accepted, Diagnostic, Diagnostics, None, Outcome, PortLocus, Rejected, Some, outcome_rejected } import v4.std.logic { Bool } import v4.std.node { Atom, Conj, Node, Symbol, TypeNode, SyntheticOccurrence } import v4.std.verification { diff --git a/src/v4/test/claim/lens_cost/loop_illegal_named.dag b/src/v4/test/claim/lens_cost/loop_illegal_named.dag index 05d9005ea74..d3c0bba7369 100644 --- a/src/v4/test/claim/lens_cost/loop_illegal_named.dag +++ b/src/v4/test/claim/lens_cost/loop_illegal_named.dag @@ -5,6 +5,7 @@ module v4.test.claim.lens_cost.loop_illegal_named import v4.lens.cost { cost_lens } +import v4.std.diagnostic { Diagnostic } import v4.std.cardinality { cardinality_loop_bound_malformed } import v4.std.logic { Bool } import v4.std.node { diff --git a/src/v4/test/claim/manual/bootstrap_footprint_anchor.dag b/src/v4/test/claim/manual/bootstrap_footprint_anchor.dag index ebbbc17bfb5..a41e34f4ea6 100644 --- a/src/v4/test/claim/manual/bootstrap_footprint_anchor.dag +++ b/src/v4/test/claim/manual/bootstrap_footprint_anchor.dag @@ -13,6 +13,7 @@ import v4.extdeps.runtimes.v4_evaluator { v4_evaluator_runtime_wave1, v4_evaluator_value_representation_wave1 } +import v4.std.diagnostic { Diagnostic } import v4.std.runtime { ResourceEffectBoundary } import v4.std.node { Atom, Node, Symbol, TypeNode, content_hash, SyntheticOccurrence } import v4.std.verification { diff --git a/src/v4/test/claim/manual/comprep_eval_by_execution.dag b/src/v4/test/claim/manual/comprep_eval_by_execution.dag index a3fe5d03071..895fe282a9f 100644 --- a/src/v4/test/claim/manual/comprep_eval_by_execution.dag +++ b/src/v4/test/claim/manual/comprep_eval_by_execution.dag @@ -45,6 +45,7 @@ import v4.std.diagnostic { outcome_accepted, outcome_rejected } +import v4.std.grammar { ParseTree } import v4.std.lexing { Token } import v4.std.machine { Byte } import v4.std.node { @@ -92,6 +93,10 @@ import v4.std.verification { manual_claim_anchor } +fn comprep_eval_parse_tree_to_node(tree: ParseTree) -> Node { + tree +} + fn comprep_eval_atom(s: Symbol) -> Node { Node { kind: TypeNode { connective: Atom { identity: s } }, @@ -272,7 +277,7 @@ fn comprep_source_ingested_add_infers() -> Outcome { o: comprep_wave1_add_parse_tokens(tokens: tokens.tokens), f: fn(parsed) { bind_outcome( - o: normalize(parse_tree: parsed), + o: normalize(parse_tree: comprep_eval_parse_tree_to_node(tree: parsed)), f: fn(normalized) { bind_outcome( o: resolve(tree: normalized, lm: lm), @@ -321,7 +326,7 @@ fn comprep_eval_normalize_holds() -> Bool { Accepted { value: tokens, diagnostics: _ } => match comprep_wave1_add_parse_tokens(tokens: tokens) { Accepted { value: parsed, diagnostics: _ } => - match normalize(parse_tree: parsed) { + match normalize(parse_tree: comprep_eval_parse_tree_to_node(tree: parsed)) { Accepted { value: _, diagnostics: _ } => true Rejected { diagnostics: _ } => false } @@ -337,7 +342,7 @@ fn comprep_eval_resolve_holds() -> Bool { Accepted { value: tokens, diagnostics: _ } => match comprep_wave1_add_parse_tokens(tokens: tokens) { Accepted { value: parsed, diagnostics: _ } => - match normalize(parse_tree: parsed) { + match normalize(parse_tree: comprep_eval_parse_tree_to_node(tree: parsed)) { Accepted { value: normalized, diagnostics: _ } => match resolve(tree: normalized, lm: lm) { Accepted { value: _, diagnostics: _ } => true diff --git a/src/v4/test/claim/manual/comprep_value_expression_fold_typescript.dag b/src/v4/test/claim/manual/comprep_value_expression_fold_typescript.dag index 5f526d8ae7c..842f0a66ed3 100644 --- a/src/v4/test/claim/manual/comprep_value_expression_fold_typescript.dag +++ b/src/v4/test/claim/manual/comprep_value_expression_fold_typescript.dag @@ -44,6 +44,7 @@ import v4.std.node { Named, Node, Positional, + Symbol, TypeNode, content_hash, node_synthetic diff --git a/src/v4/test/claim/manual/effect_io_eval_by_execution.dag b/src/v4/test/claim/manual/effect_io_eval_by_execution.dag index 5acef5e58df..ac9be413378 100644 --- a/src/v4/test/claim/manual/effect_io_eval_by_execution.dag +++ b/src/v4/test/claim/manual/effect_io_eval_by_execution.dag @@ -34,6 +34,7 @@ import v4.std.cardinality { RankingDimension, TerminationProof } import v4.std.collection { List, Map } import v4.std.diagnostic { Accepted, + None, Outcome, Rejected, diagnostics_singleton diff --git a/src/v4/test/claim/manual/find_witness_project_to_core_controls.dag b/src/v4/test/claim/manual/find_witness_project_to_core_controls.dag index cde23ef49c3..29e8110e0b8 100644 --- a/src/v4/test/claim/manual/find_witness_project_to_core_controls.dag +++ b/src/v4/test/claim/manual/find_witness_project_to_core_controls.dag @@ -12,6 +12,7 @@ import v4.test.fixture.derivable_coercion_task_id { task_id_db_inhabitant_node, task_id_wire_inhabitant_node } +import v4.std.algebra { Equal, Less } import v4.std.collection { List } import v4.std.find_witness { CandidateSet, diff --git a/src/v4/test/claim/manual/infer_ground_add_mvp.dag b/src/v4/test/claim/manual/infer_ground_add_mvp.dag index f67235038b4..5a2d79d62ff 100644 --- a/src/v4/test/claim/manual/infer_ground_add_mvp.dag +++ b/src/v4/test/claim/manual/infer_ground_add_mvp.dag @@ -350,6 +350,7 @@ fn infer_descent_witness_receipt_run( fn fixture_add_resolved_node() -> Node { fixture_add_resolved_tree() } + fn fixture_add_resolved_tree() -> ResolvedTree { Node { kind: TypeNode { connective: Conj }, @@ -382,7 +383,7 @@ fn fixture_add_resolved_tree() -> ResolvedTree { fn anchor_infer_add_mvp() -> Outcome { - infer(tree: fixture_add_resolved_tree()) + infer(tree: fixture_add_resolved_node()) } diff --git a/src/v4/test/claim/manual/map_structural_key_equality.dag b/src/v4/test/claim/manual/map_structural_key_equality.dag index f997c235f2e..01f3cf28106 100644 --- a/src/v4/test/claim/manual/map_structural_key_equality.dag +++ b/src/v4/test/claim/manual/map_structural_key_equality.dag @@ -28,7 +28,7 @@ type SKey { type SKeyMap = Map -fn one_entry(a: Int, b: Int, v: Int) -> SKeyMap { +fn one_entry(a: Int, b: Int, v: Int) -> Map { map_insert(m: empty_map(), key: SKey { a: a, b: b }, value: v) } diff --git a/src/v4/test/claim/manual/mvp1_cpp_add_translate.dag b/src/v4/test/claim/manual/mvp1_cpp_add_translate.dag index dbb657b2ae9..12547af690d 100644 --- a/src/v4/test/claim/manual/mvp1_cpp_add_translate.dag +++ b/src/v4/test/claim/manual/mvp1_cpp_add_translate.dag @@ -44,7 +44,7 @@ import v4.extdeps.languages.cpp { } import v4.compiler.infer { InferredFacts, InferredTree } import v4.compiler.target_carriers { TargetSource } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.test.claim.lens_common.infer_fixture { claim_inferred_facts_witness } import v4.test.claim.manual.infer_ground_add_mvp { infer_receipt_context @@ -136,9 +136,17 @@ data mvp1_cpp_missing_translation_rules_target: TargetModel = TargetModel { authority_source_text: "" } +fn mvp1_cpp_target_model_bundle() -> TargetModelBundle { + mvp1_cpp_target_model +} + +fn mvp1_cpp_missing_translation_rules_bundle() -> TargetModelBundle { + mvp1_cpp_missing_translation_rules_target +} + fn anchor_mvp1_cpp_serialize_rejects_missing_translation_rules() -> Outcome { target_serialize_source_from_model( - target: mvp1_cpp_missing_translation_rules_target, + target: mvp1_cpp_missing_translation_rules_bundle(), emitted: mvp1_cpp_emitted_root ) } @@ -313,7 +321,7 @@ data mvp1_cpp_inferred_tree: InferredTree = InferredTree { } fn anchor_mvp1_cpp_emit_accepts() -> Outcome { - emit(tree: mvp1_cpp_inferred_tree, target: mvp1_cpp_target_model) + emit(tree: mvp1_cpp_inferred_tree, target: mvp1_cpp_target_model_bundle()) } fn anchor_mvp1_cpp_compile_inferred_accepts() -> Outcome { diff --git a/src/v4/test/claim/manual/mvp1_dag_add_round_trip.dag b/src/v4/test/claim/manual/mvp1_dag_add_round_trip.dag index 5219c281cae..2af9baf2ad2 100644 --- a/src/v4/test/claim/manual/mvp1_dag_add_round_trip.dag +++ b/src/v4/test/claim/manual/mvp1_dag_add_round_trip.dag @@ -40,7 +40,7 @@ import v4.std.diagnostic { } import v4.std.logic { Bool } import v4.std.node { Node } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.std.witness { Holds, StructuralPropertyWitness, Violates, Witness } import v4.std.verification { @@ -52,6 +52,10 @@ data mvp1_dag_emitted_root: Node = dag_mvp1_fixture_emitted_add_fn data mvp1_dag_target_model: TargetModel = dag_mvp1_target_model() +fn mvp1_dag_target_model_bundle() -> TargetModelBundle { + mvp1_dag_target_model +} + fn mvp1_dag_canonical_grounding( node: Node, algebra: Node @@ -140,7 +144,7 @@ data mvp1_dag_inferred_tree: InferredTree = InferredTree { } fn anchor_mvp1_dag_emit_accepts() -> Outcome { - emit(tree: mvp1_dag_inferred_tree, target: mvp1_dag_target_model) + emit(tree: mvp1_dag_inferred_tree, target: mvp1_dag_target_model_bundle()) } data mvp1_dag_emit_receipt: Outcome = anchor_mvp1_dag_emit_accepts() @@ -155,7 +159,7 @@ fn mvp1_dag_coercion_quality_is_faithful(q: CoercionQuality) -> Bool { fn mvp1_dag_emit_matches_serialize_holds() -> Bool { match target_serialize_source_from_model( - target: mvp1_dag_target_model, + target: mvp1_dag_target_model_bundle(), emitted: mvp1_dag_emitted_root ) { Accepted { value: authority, diagnostics: ad } => @@ -170,7 +174,7 @@ fn mvp1_dag_emit_matches_serialize_holds() -> Bool { fn mvp1_dag_grammar_inverse_holds() -> Bool { match grammar_inverse_source_validated( - target: mvp1_dag_target_model, + target: mvp1_dag_target_model_bundle(), emitted: mvp1_dag_emitted_root ) { Accepted { value: _, diagnostics: d } => d == None @@ -182,7 +186,7 @@ fn mvp1_dag_ingest_via_coerce_matches_canonical() -> Bool { match coerce_grounded_node( source: mvp1_dag_emitted_root, tree: mvp1_dag_inferred_tree, - target: mvp1_dag_target_model + target: mvp1_dag_target_model_bundle() ) { Accepted { value: result, diagnostics: d } => (result.target == dag_mvp1_fixture_emitted_add_fn) diff --git a/src/v4/test/claim/manual/mvp1_go_add_translate.dag b/src/v4/test/claim/manual/mvp1_go_add_translate.dag index 2466a42c3f6..076823bdc8b 100644 --- a/src/v4/test/claim/manual/mvp1_go_add_translate.dag +++ b/src/v4/test/claim/manual/mvp1_go_add_translate.dag @@ -28,6 +28,7 @@ import v4.extdeps.languages.go { SignedPlatformInt, SignedTypedIntegerTruncatesSilentlyOnOverflow, go_facts_int, + go_mvp1_emitted_add_fn_node, go_inhabitant_atom, go_int_inhabitant_node, go_int_kind_node, @@ -43,7 +44,7 @@ import v4.extdeps.languages.go { } import v4.compiler.infer { InferredFacts, InferredTree } import v4.compiler.target_carriers { TargetSource } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.test.claim.lens_common.infer_fixture { claim_inferred_facts_witness } import v4.test.claim.manual.infer_ground_add_mvp { infer_receipt_context @@ -127,9 +128,17 @@ data mvp1_go_missing_translation_rules_target: TargetModel = TargetModel { authority_source_text: "" } +fn mvp1_go_target_model_bundle() -> TargetModelBundle { + mvp1_go_target_model +} + +fn mvp1_go_missing_translation_rules_bundle() -> TargetModelBundle { + mvp1_go_missing_translation_rules_target +} + fn anchor_mvp1_go_serialize_rejects_missing_translation_rules() -> Outcome { target_serialize_source_from_model( - target: mvp1_go_missing_translation_rules_target, + target: mvp1_go_missing_translation_rules_bundle(), emitted: mvp1_go_emitted_root ) } @@ -304,7 +313,7 @@ data mvp1_go_inferred_tree: InferredTree = InferredTree { } fn anchor_mvp1_go_emit_accepts() -> Outcome { - emit(tree: mvp1_go_inferred_tree, target: mvp1_go_target_model) + emit(tree: mvp1_go_inferred_tree, target: mvp1_go_target_model_bundle()) } fn anchor_mvp1_go_compile_inferred_accepts() -> Outcome { diff --git a/src/v4/test/claim/manual/mvp1_python_add_translate.dag b/src/v4/test/claim/manual/mvp1_python_add_translate.dag index 640a2276a52..7949bbdd3ee 100644 --- a/src/v4/test/claim/manual/mvp1_python_add_translate.dag +++ b/src/v4/test/claim/manual/mvp1_python_add_translate.dag @@ -36,7 +36,7 @@ import v4.extdeps.languages.python { } import v4.compiler.infer { InferredFacts, InferredTree } import v4.compiler.target_carriers { TargetSource } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.test.claim.lens_common.infer_fixture { claim_inferred_facts_witness } import v4.test.claim.manual.infer_ground_add_mvp { infer_receipt_context @@ -120,9 +120,17 @@ data mvp1_python_missing_translation_rules_target: TargetModel = TargetModel { authority_source_text: "" } +fn mvp1_python_target_model_bundle() -> TargetModelBundle { + mvp1_python_target_model +} + +fn mvp1_python_missing_translation_rules_bundle() -> TargetModelBundle { + mvp1_python_missing_translation_rules_target +} + fn anchor_mvp1_python_serialize_rejects_missing_translation_rules() -> Outcome { target_serialize_source_from_model( - target: mvp1_python_missing_translation_rules_target, + target: mvp1_python_missing_translation_rules_bundle(), emitted: mvp1_python_emitted_root ) } @@ -255,7 +263,7 @@ data mvp1_python_inferred_tree: InferredTree = InferredTree { } fn anchor_mvp1_python_emit_accepts() -> Outcome { - emit(tree: mvp1_python_inferred_tree, target: mvp1_python_target_model) + emit(tree: mvp1_python_inferred_tree, target: mvp1_python_target_model_bundle()) } fn anchor_mvp1_python_compile_inferred_accepts() -> Outcome { diff --git a/src/v4/test/claim/manual/mvp1_rust_add_translate.dag b/src/v4/test/claim/manual/mvp1_rust_add_translate.dag index 484e030024d..e8c3fd7d30b 100644 --- a/src/v4/test/claim/manual/mvp1_rust_add_translate.dag +++ b/src/v4/test/claim/manual/mvp1_rust_add_translate.dag @@ -48,7 +48,7 @@ import v4.extdeps.languages.rust { } import v4.compiler.infer { InferredFacts, InferredTree } import v4.compiler.target_carriers { TargetSource } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.test.claim.lens_common.infer_fixture { claim_inferred_facts_witness } import v4.test.claim.manual.infer_ground_add_mvp { infer_receipt_context @@ -123,7 +123,7 @@ data mvp_add_arrow_node: Node = Node { data mvp1_rust_emitted_root: Node = rust_mvp1_fixture_emitted_add_fn -data mvp1_rust_target_model: TargetModel = rust_mvp1_target_model() +data mvp1_rust_target_model: TargetModelBundle = rust_mvp1_target_model() data mvp1_rust_poisoned_authority_target_model: TargetModel = TargetModel { bundle: rust_mvp1_target_model_node(), @@ -146,9 +146,13 @@ data mvp1_rust_missing_translation_rules_target: TargetModel = TargetModel { authority_source_text: "" } +fn mvp1_rust_missing_translation_rules_bundle() -> TargetModelBundle { + mvp1_rust_missing_translation_rules_target +} + fn anchor_mvp1_serialize_rejects_missing_translation_rules() -> Outcome { target_serialize_source_from_model( - target: mvp1_rust_missing_translation_rules_target, + target: mvp1_rust_missing_translation_rules_bundle(), emitted: mvp1_rust_emitted_root ) } diff --git a/src/v4/test/claim/manual/mvp1_typescript_add_translate.dag b/src/v4/test/claim/manual/mvp1_typescript_add_translate.dag index 6c816d35f3c..62dc93d4329 100644 --- a/src/v4/test/claim/manual/mvp1_typescript_add_translate.dag +++ b/src/v4/test/claim/manual/mvp1_typescript_add_translate.dag @@ -38,7 +38,7 @@ import v4.extdeps.languages.typescript { } import v4.compiler.infer { InferredFacts, InferredTree } import v4.compiler.target_carriers { TargetSource } -import v4.std.target_model { TargetModel } +import v4.std.target_model { TargetModel, TargetModelBundle } import v4.test.claim.lens_common.infer_fixture { claim_inferred_facts_witness } import v4.test.claim.manual.infer_ground_add_mvp { infer_receipt_context @@ -125,9 +125,17 @@ data mvp1_ts_missing_translation_rules_target: TargetModel = TargetModel { authority_source_text: "" } +fn mvp1_ts_target_model_bundle() -> TargetModelBundle { + mvp1_ts_target_model +} + +fn mvp1_ts_missing_translation_rules_bundle() -> TargetModelBundle { + mvp1_ts_missing_translation_rules_target +} + fn anchor_mvp1_ts_serialize_rejects_missing_translation_rules() -> Outcome { target_serialize_source_from_model( - target: mvp1_ts_missing_translation_rules_target, + target: mvp1_ts_missing_translation_rules_bundle(), emitted: mvp1_ts_emitted_root ) } @@ -295,7 +303,7 @@ data mvp1_ts_inferred_tree: InferredTree = InferredTree { } fn anchor_mvp1_ts_emit_accepts() -> Outcome { - emit(tree: mvp1_ts_inferred_tree, target: mvp1_ts_target_model) + emit(tree: mvp1_ts_inferred_tree, target: mvp1_ts_target_model_bundle()) } fn anchor_mvp1_ts_compile_inferred_accepts() -> Outcome { diff --git a/src/v4/test/claim/manual/parallel_executor.dag b/src/v4/test/claim/manual/parallel_executor.dag index 68902639e75..1ddc739f2f7 100644 --- a/src/v4/test/claim/manual/parallel_executor.dag +++ b/src/v4/test/claim/manual/parallel_executor.dag @@ -5,7 +5,7 @@ module v4.test.claim.manual.parallel_executor import v4.std.collection { List } -import v4.std.dependency { ReadinessLayer } +import v4.std.dependency { DependencyView, ReadinessLayer } import v4.std.logic { Bool } import v4.std.verification { BoolWitness, BoolWitnessClaim, UnifiedTestClaim } import v4.workflow.executor { diff --git a/src/v4/test/claim/manual/posix_output_capture.dag b/src/v4/test/claim/manual/posix_output_capture.dag index 5d5ef47aa04..2d465b42c7d 100644 --- a/src/v4/test/claim/manual/posix_output_capture.dag +++ b/src/v4/test/claim/manual/posix_output_capture.dag @@ -7,7 +7,7 @@ module v4.test.claim.manual.posix_output_capture import v4.extdeps.posix { CapturedOutputPipes } -import v4.std.algebra { is_empty } +import v4.std.algebra { Empty, is_empty } import v4.std.node { Node } import v4.std.verification { EqualsClaim, diff --git a/src/v4/test/claim/manual/typescript_derive_grammar_relation_row_round_trip.dag b/src/v4/test/claim/manual/typescript_derive_grammar_relation_row_round_trip.dag index 0dcda48219f..f1e8cb160be 100644 --- a/src/v4/test/claim/manual/typescript_derive_grammar_relation_row_round_trip.dag +++ b/src/v4/test/claim/manual/typescript_derive_grammar_relation_row_round_trip.dag @@ -26,6 +26,7 @@ import v4.std.grammar { grammar_relation_tokens_node } +import v4.std.diagnostic { Diagnostic } import v4.std.logic { Bool } import v4.std.witness { Holds, Violates, Witness } import v4.std.node { Atom, Conj, Edge, Node, Positional, Symbol, TypeNode, content_hash, SyntheticOccurrence } diff --git a/src/v4/test/claim/manual/v4_evaluator_runtime_anchor.dag b/src/v4/test/claim/manual/v4_evaluator_runtime_anchor.dag index 80d3a1e1d0e..3ee90fa30f3 100644 --- a/src/v4/test/claim/manual/v4_evaluator_runtime_anchor.dag +++ b/src/v4/test/claim/manual/v4_evaluator_runtime_anchor.dag @@ -38,9 +38,7 @@ import v4.std.verification { Unit, manual_claim_anchor } -type v4_evaluator_anchor_runtime_type = V4EvaluatorRuntime - -data v4_evaluator_anchor_runtime: v4_evaluator_anchor_runtime_type = v4_evaluator_runtime_wave1() +data v4_evaluator_anchor_runtime: V4EvaluatorRuntime = v4_evaluator_runtime_wave1() data v4_evaluator_anchor_core: ModelCore = v4_evaluator_anchor_runtime.core diff --git a/src/v4/test/claim/provenance/occurrence_id_model.dag b/src/v4/test/claim/provenance/occurrence_id_model.dag index 7c85f23575a..d2f85ac0153 100644 --- a/src/v4/test/claim/provenance/occurrence_id_model.dag +++ b/src/v4/test/claim/provenance/occurrence_id_model.dag @@ -13,6 +13,7 @@ import v4.std.node { Conj, Edge, Node, + OccurrenceId, Positional, Symbol, TypeNode, diff --git a/src/v4/test/claim/std_text/carrier_claims.dag b/src/v4/test/claim/std_text/carrier_claims.dag index 23ff6c43e3d..5d8f465b1be 100644 --- a/src/v4/test/claim/std_text/carrier_claims.dag +++ b/src/v4/test/claim/std_text/carrier_claims.dag @@ -19,9 +19,9 @@ module v4.test.claim.std_text.carrier_claims -import v4.std.algebra { Cons, Empty, Equal, FreeMonoid, Ordering } +import v4.std.algebra { Cons, Empty, FreeMonoid } import v4.std.logic { Bool } -import v4.std.nat { Nat, Succ, Zero, nat_compare } +import v4.std.nat { Succ, Zero } import v4.std.text { Char, CharAbsent, @@ -51,12 +51,8 @@ fn text_not(b: Bool) -> Bool { } -// Char equality via the substrate total-order compare (no reliance on `==` over Nat). fn text_char_eq(a: Char, b: Char) -> Bool { - match nat_compare(a: a, b: b) { - Equal => true - _ => false - } + a == b } diff --git a/src/v4/test/claim/workflow/affected_testgen_ci_runner.dag b/src/v4/test/claim/workflow/affected_testgen_ci_runner.dag index c4cdf17f4e5..40e37fbaee7 100644 --- a/src/v4/test/claim/workflow/affected_testgen_ci_runner.dag +++ b/src/v4/test/claim/workflow/affected_testgen_ci_runner.dag @@ -119,7 +119,6 @@ data affected_testgen_source_dependency_provenance: NodeArtifactProvenance = Nod artifact: affected_testgen_source_dependency_artifact } - data affected_testgen_git_diff: GitDiffNameOnly = GitDiffNameOnly { changed_paths: [affected_testgen_path_witness_validity] } diff --git a/src/v4/workflow/bootstrap.dag b/src/v4/workflow/bootstrap.dag index b208af65271..f1e24217a4c 100644 --- a/src/v4/workflow/bootstrap.dag +++ b/src/v4/workflow/bootstrap.dag @@ -16,6 +16,7 @@ import v4.std.algebra { import v4.compiler.target_carriers { LanguageModel } import v4.std.target_model { TargetModel, + TargetModelBundle, target_model_edge_selection_policy, target_model_edge_translation_rules } @@ -55,7 +56,7 @@ type BootstrapSourceSnapshot { type BootstrapProjectionInputs { snapshot: BootstrapSourceSnapshot - target_model: TargetModel + target_model: TargetModelBundle runtime_model: V4EvaluatorRuntime } @@ -295,7 +296,7 @@ fn bootstrap_target_model_bundle_construct_fold_state(root: Node) -> BootstrapCo fold_node(n: root, algebra: bootstrap_target_model_bundle_construct_fold_algebra()) } -fn bootstrap_target_model_construct_inventory(target: TargetModel) -> List { +fn bootstrap_target_model_construct_inventory(target: TargetModelBundle) -> List { bootstrap_target_model_bundle_construct_fold_state(root: target.bundle).constructs } @@ -756,16 +757,28 @@ fn bootstrap_stage_output(plan: Outcome, s: Symbol) -> Bool { } } +fn bootstrap_seed_consumes() -> List { + [^v4_dag_source] +} + +fn bootstrap_self0_consumes() -> List { + [^v4_dag_source, ^v4_stage0_binary] +} + +fn bootstrap_self1_consumes() -> List { + [^v4_dag_source, ^v4_stage1_binary] +} + fn bootstrap_plan_well_formed(p: BootstrapPlan) -> Outcome { match bootstrap_fixpt_witness(f: p.fixpt) { Holds { value: _ } => - if bs_list_eq(a: p.seed.consumes, b: [^v4_dag_source]) + if bs_list_eq(a: p.seed.consumes, b: bootstrap_seed_consumes()) && (p.seed.produces == ^v4_stage0_binary) && (p.seed.compiled_by == ^v2_pipeline) - && bs_list_eq(a: p.self0.consumes, b: [^v4_dag_source, ^v4_stage0_binary]) + && bs_list_eq(a: p.self0.consumes, b: bootstrap_self0_consumes()) && (p.self0.produces == ^v4_stage1_binary) && (p.self0.compiled_by == ^v4_stage0_binary) - && bs_list_eq(a: p.self1.consumes, b: [^v4_dag_source, ^v4_stage1_binary]) + && bs_list_eq(a: p.self1.consumes, b: bootstrap_self1_consumes()) && (p.self1.produces == ^v4_stage2_binary) && (p.self1.compiled_by == ^v4_stage1_binary) && (p.seed.produces_hash.pin == ^v4_stage0_hash_pin) diff --git a/src/v4/workflow/executor.dag b/src/v4/workflow/executor.dag index b1a0b04bc31..d0d5e6ace5f 100644 --- a/src/v4/workflow/executor.dag +++ b/src/v4/workflow/executor.dag @@ -7,6 +7,8 @@ module v4.workflow.executor import v4.std.algebra { + Empty, + FreeMonoid, contains, list_snoc_item, non_empty @@ -85,12 +87,12 @@ fn executor_batch_for_frontier(frontier: RunnableFrontier) -> ExecutorBatch { } fn executor_job_nodes(jobs: List) -> List { - fold(jobs, init: [], f: fn(nodes, job) { + fold(jobs, init: Empty, f: fn(nodes, job) { list_snoc_item(xs: nodes, item: job.node) }) } -fn executor_append_batch(batches: List, batch: ExecutorBatch) -> List { +fn executor_append_batch(batches: FreeMonoid, batch: ExecutorBatch) -> FreeMonoid { if non_empty(xs: batch.jobs) { list_snoc_item(xs: batches, item: batch) } else { diff --git a/src/v4/workflow/scheduler.dag b/src/v4/workflow/scheduler.dag index a3ccbad4d30..ab0c15f99ae 100644 --- a/src/v4/workflow/scheduler.dag +++ b/src/v4/workflow/scheduler.dag @@ -7,6 +7,8 @@ module v4.workflow.scheduler import v4.std.collection { List, list_at_optional, optional_present_witness } import v4.std.algebra { + Empty, + FreeMonoid, contains, filter, for_all, @@ -94,7 +96,7 @@ fn scheduler_execution_dependencies(dependencies: List) -> List< filter(xs: dependencies, predicate: scheduler_dependency_orders_execution) } -fn scheduler_append_node_once(nodes: List, node: Node) -> List { +fn scheduler_append_node_once(nodes: FreeMonoid, node: Node) -> FreeMonoid { if contains(xs: nodes, item: node, eq: fn(left, right) { left == right }) { nodes } else { @@ -103,7 +105,7 @@ fn scheduler_append_node_once(nodes: List, node: Node) -> List { } fn scheduler_dependency_nodes(dependencies: List) -> List { - fold(dependencies, init: [], f: fn(nodes, dependency) { + fold(dependencies, init: Empty, f: fn(nodes, dependency) { scheduler_append_node_once( nodes: scheduler_append_node_once(nodes: nodes, node: dependency.source), node: dependency.dependent @@ -184,7 +186,7 @@ fn scheduler_schedule_frontier(scheduled: List, frontier: RunnableFrontier }) } -fn scheduler_append_frontier_layer(layers: List, frontier: RunnableFrontier) -> List { +fn scheduler_append_frontier_layer(layers: FreeMonoid, frontier: RunnableFrontier) -> FreeMonoid { if non_empty(xs: frontier.ready) { list_snoc_item( xs: layers,