From 5a25f3c2ca30891f3cdc22b9a09150198a56b299 Mon Sep 17 00:00:00 2001 From: TeRiRi_606 <147689545+OttoApocalypse69@users.noreply.github.com> Date: Thu, 13 Aug 2026 20:21:34 +0300 Subject: [PATCH 1/5] Move ordinary task parameters into HIR - Store ordered parameter semantics and spans in HIR snapshot v6\n- Route TY, MIR, and editor consumers through semantic adapters\n- Add boundary, restore, and invalidation smoke coverage --- .../v4/crates/freak_editor/src/lib.fk | 12 +- src/compiler/v4/crates/freak_hir/src/lib.fk | 851 +++++++++++++++++- .../v4/crates/freak_mir_build/src/lib.fk | 7 +- src/compiler/v4/crates/freak_ty/src/lib.fk | 166 +++- .../task_param_semantic_boundary_smoke.fk | 330 +++++++ 5 files changed, 1305 insertions(+), 61 deletions(-) create mode 100644 src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk diff --git a/src/compiler/v4/crates/freak_editor/src/lib.fk b/src/compiler/v4/crates/freak_editor/src/lib.fk index 728a0663..bca0e77f 100644 --- a/src/compiler/v4/crates/freak_editor/src/lib.fk +++ b/src/compiler/v4/crates/freak_editor/src/lib.fk @@ -580,17 +580,7 @@ task v4_editor_signature_param_name_span(ty_id: int, sig_id: int, param_name: wo if param_id < 0 { give back V4_NO_SPAN } - pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - if stream_id < 0 or start_token < 0 { - give back V4_NO_SPAN - } - pilot end_token = v4_ty_signature_param_segment_end(ty_id, sig_id, param_id) - pilot name_token = v4_ty_find_token_value(stream_id, start_token, end_token, param_name) - if name_token < 0 or name_token >= end_token { - give back V4_NO_SPAN - } - give back v4_lex_token_span(stream_id, name_token) + give back v4_ty_signature_param_name_span(ty_id, sig_id, param_id) } task v4_editor_impl_method_explicit_param_id_for_name(ty_id: int, hir_item: int, method_id: int, param_name: word) -> int { diff --git a/src/compiler/v4/crates/freak_hir/src/lib.fk b/src/compiler/v4/crates/freak_hir/src/lib.fk index 77ebb1ce..e2a5c38f 100644 --- a/src/compiler/v4/crates/freak_hir/src/lib.fk +++ b/src/compiler/v4/crates/freak_hir/src/lib.fk @@ -17,10 +17,13 @@ pilot v4_hir_import = "Import" pilot v4_hir_extern = "Extern" pilot v4_hir_attribute = "Attribute" pilot v4_hir_error = "Error" -pilot v4_hir_snapshot_format = "freak-hir-snapshot-v5" +pilot v4_hir_snapshot_format = "freak-hir-snapshot-v6" pilot v4_hir_task_return_explicit = "explicit" pilot v4_hir_task_return_implicit_block = "implicit-block" pilot v4_hir_task_return_arrow = "arrow" +pilot v4_hir_task_param_mode_value = "value" +pilot v4_hir_task_param_mode_lend = "lend" +pilot v4_hir_task_param_mode_lend_mut = "lend mut" pilot v4_hir_files = 0 pilot v4_hir_expansions = 0 @@ -46,6 +49,21 @@ pilot v4_hir_task_return_items = 0 pilot v4_hir_task_return_forms = 0 pilot v4_hir_task_return_types = 0 pilot v4_hir_task_return_spans = 0 +-- Every ordinary top-level task owns one parameter-count record, including +-- zero-parameter tasks. Valid parameters are normalized into ordered child +-- records so lower layers never need to reinterpret the signature tokens. +pilot v4_hir_task_param_owner_items = 0 +pilot v4_hir_task_param_owner_counts = 0 +pilot v4_hir_task_param_items = 0 +pilot v4_hir_task_param_ordinals = 0 +pilot v4_hir_task_param_names = 0 +pilot v4_hir_task_param_name_spans = 0 +pilot v4_hir_task_param_modes = 0 +pilot v4_hir_task_param_lifetimes = 0 +pilot v4_hir_task_param_lifetime_spans = 0 +pilot v4_hir_task_param_types = 0 +pilot v4_hir_task_param_type_spans = 0 +pilot v4_hir_task_param_segment_spans = 0 pilot v4_hir_diags = 0 pilot v4_hir_file_len = 0 pilot v4_hir_ready = 0 @@ -69,6 +87,18 @@ task v4_hir_init() -> void { v4_hir_task_return_forms = array_new() v4_hir_task_return_types = array_new() v4_hir_task_return_spans = array_new() + v4_hir_task_param_owner_items = array_new() + v4_hir_task_param_owner_counts = array_new() + v4_hir_task_param_items = array_new() + v4_hir_task_param_ordinals = array_new() + v4_hir_task_param_names = array_new() + v4_hir_task_param_name_spans = array_new() + v4_hir_task_param_modes = array_new() + v4_hir_task_param_lifetimes = array_new() + v4_hir_task_param_lifetime_spans = array_new() + v4_hir_task_param_types = array_new() + v4_hir_task_param_type_spans = array_new() + v4_hir_task_param_segment_spans = array_new() v4_hir_diags = array_new() v4_hir_file_len = 0 v4_hir_ready = 1 @@ -96,6 +126,18 @@ task v4_hir_file_new(file_id: int, expansion_id: int) -> int { array_push(v4_hir_task_return_forms, word_from_int(array_new())) array_push(v4_hir_task_return_types, word_from_int(array_new())) array_push(v4_hir_task_return_spans, word_from_int(array_new())) + array_push(v4_hir_task_param_owner_items, word_from_int(array_new())) + array_push(v4_hir_task_param_owner_counts, word_from_int(array_new())) + array_push(v4_hir_task_param_items, word_from_int(array_new())) + array_push(v4_hir_task_param_ordinals, word_from_int(array_new())) + array_push(v4_hir_task_param_names, word_from_int(array_new())) + array_push(v4_hir_task_param_name_spans, word_from_int(array_new())) + array_push(v4_hir_task_param_modes, word_from_int(array_new())) + array_push(v4_hir_task_param_lifetimes, word_from_int(array_new())) + array_push(v4_hir_task_param_lifetime_spans, word_from_int(array_new())) + array_push(v4_hir_task_param_types, word_from_int(array_new())) + array_push(v4_hir_task_param_type_spans, word_from_int(array_new())) + array_push(v4_hir_task_param_segment_spans, word_from_int(array_new())) array_push(v4_hir_diags, word_from_int(array_new())) } array_set(v4_hir_files, hir_id, word_from_int(file_id)) @@ -115,6 +157,18 @@ task v4_hir_file_new(file_id: int, expansion_id: int) -> int { array_set(v4_hir_task_return_forms, hir_id, word_from_int(array_new())) array_set(v4_hir_task_return_types, hir_id, word_from_int(array_new())) array_set(v4_hir_task_return_spans, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_owner_items, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_owner_counts, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_items, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_ordinals, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_names, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_name_spans, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_modes, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_lifetimes, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_lifetime_spans, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_types, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_type_spans, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_segment_spans, hir_id, word_from_int(array_new())) array_set(v4_hir_diags, hir_id, word_from_int(array_new())) v4_hir_file_len = hir_id + 1 give back hir_id @@ -180,6 +234,54 @@ task v4_hir_task_return_spans_handle(hir_id: int) -> int { give back word_to_int(array_get(v4_hir_task_return_spans, hir_id)) } +task v4_hir_task_param_owner_items_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_owner_items, hir_id)) +} + +task v4_hir_task_param_owner_counts_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_owner_counts, hir_id)) +} + +task v4_hir_task_param_items_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_items, hir_id)) +} + +task v4_hir_task_param_ordinals_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_ordinals, hir_id)) +} + +task v4_hir_task_param_names_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_names, hir_id)) +} + +task v4_hir_task_param_name_spans_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_name_spans, hir_id)) +} + +task v4_hir_task_param_modes_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_modes, hir_id)) +} + +task v4_hir_task_param_lifetimes_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_lifetimes, hir_id)) +} + +task v4_hir_task_param_lifetime_spans_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_lifetime_spans, hir_id)) +} + +task v4_hir_task_param_types_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_types, hir_id)) +} + +task v4_hir_task_param_type_spans_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_type_spans, hir_id)) +} + +task v4_hir_task_param_segment_spans_handle(hir_id: int) -> int { + give back word_to_int(array_get(v4_hir_task_param_segment_spans, hir_id)) +} + task v4_hir_diags_handle(hir_id: int) -> int { give back word_to_int(array_get(v4_hir_diags, hir_id)) } @@ -619,6 +721,141 @@ task v4_hir_add_task_return(hir_id: int, item_id: int, form: word, type_text: wo give back record_id } +task v4_hir_item_decl_is_ordinary_task(hir_id: int, item_id: int) -> bool { + if hir_id < 0 or item_id < 0 or item_id >= v4_hir_item_count(hir_id) { + give back false + } + if v4_hir_item_kind(hir_id, item_id) != v4_hir_task { + give back false + } + -- Impl/doctrine/extern signatures live beneath non-Task HIR owners. This + -- declaration-keyword check also keeps recovered non-task nodes out. + give back v4_hir_item_decl_keyword(hir_id, item_id) == "task" +} + +task v4_hir_task_param_owner_record_count(hir_id: int) -> int { + give back array_len(v4_hir_task_param_owner_items_handle(hir_id)) +} + +task v4_hir_task_param_owner_record_id(hir_id: int, item_id: int) -> int { + pilot record_id = 0 + pilot record_count = v4_hir_task_param_owner_record_count(hir_id) + repeat until record_id >= record_count { + if word_to_int(array_get(v4_hir_task_param_owner_items_handle(hir_id), record_id)) == item_id { + give back record_id + } + record_id += 1 + } + give back 0 - 1 +} + +-- The stored owner record is the semantic discriminator consumed below HIR. +-- Unlike declaration classification during lowering, this never consults an +-- expansion, parse node, source buffer, or token stream. +task v4_hir_item_is_ordinary_task(hir_id: int, item_id: int) -> bool { + if hir_id < 0 or item_id < 0 or item_id >= v4_hir_item_count(hir_id) { + give back false + } + give back v4_hir_item_kind(hir_id, item_id) == v4_hir_task and v4_hir_task_param_owner_record_id(hir_id, item_id) >= 0 +} + +task v4_hir_task_param_record_count(hir_id: int) -> int { + give back array_len(v4_hir_task_param_items_handle(hir_id)) +} + +task v4_hir_task_param_record_id(hir_id: int, item_id: int, param_id: int) -> int { + if item_id < 0 or param_id < 0 { + give back 0 - 1 + } + pilot record_id = 0 + pilot record_count = v4_hir_task_param_record_count(hir_id) + repeat until record_id >= record_count { + if word_to_int(array_get(v4_hir_task_param_items_handle(hir_id), record_id)) == item_id and word_to_int(array_get(v4_hir_task_param_ordinals_handle(hir_id), record_id)) == param_id { + give back record_id + } + record_id += 1 + } + give back 0 - 1 +} + +task v4_hir_task_param_count(hir_id: int, item_id: int) -> int { + pilot owner_record = v4_hir_task_param_owner_record_id(hir_id, item_id) + if owner_record < 0 { + give back 0 + } + give back word_to_int(array_get(v4_hir_task_param_owner_counts_handle(hir_id), owner_record)) +} + +task v4_hir_task_param_name(hir_id: int, item_id: int, param_id: int) -> word { + pilot record_id = v4_hir_task_param_record_id(hir_id, item_id, param_id) + if record_id < 0 { give back "" } + give back array_get(v4_hir_task_param_names_handle(hir_id), record_id) +} + +task v4_hir_task_param_name_span(hir_id: int, item_id: int, param_id: int) -> word { + pilot record_id = v4_hir_task_param_record_id(hir_id, item_id, param_id) + if record_id < 0 { give back V4_NO_SPAN } + give back array_get(v4_hir_task_param_name_spans_handle(hir_id), record_id) +} + +task v4_hir_task_param_mode(hir_id: int, item_id: int, param_id: int) -> word { + pilot record_id = v4_hir_task_param_record_id(hir_id, item_id, param_id) + if record_id < 0 { give back "" } + give back array_get(v4_hir_task_param_modes_handle(hir_id), record_id) +} + +task v4_hir_task_param_lifetime(hir_id: int, item_id: int, param_id: int) -> word { + pilot record_id = v4_hir_task_param_record_id(hir_id, item_id, param_id) + if record_id < 0 { give back "" } + give back array_get(v4_hir_task_param_lifetimes_handle(hir_id), record_id) +} + +task v4_hir_task_param_lifetime_span(hir_id: int, item_id: int, param_id: int) -> word { + pilot record_id = v4_hir_task_param_record_id(hir_id, item_id, param_id) + if record_id < 0 { give back V4_NO_SPAN } + give back array_get(v4_hir_task_param_lifetime_spans_handle(hir_id), record_id) +} + +task v4_hir_task_param_surface_type(hir_id: int, item_id: int, param_id: int) -> word { + pilot record_id = v4_hir_task_param_record_id(hir_id, item_id, param_id) + if record_id < 0 { give back "" } + give back array_get(v4_hir_task_param_types_handle(hir_id), record_id) +} + +task v4_hir_task_param_type_span(hir_id: int, item_id: int, param_id: int) -> word { + pilot record_id = v4_hir_task_param_record_id(hir_id, item_id, param_id) + if record_id < 0 { give back V4_NO_SPAN } + give back array_get(v4_hir_task_param_type_spans_handle(hir_id), record_id) +} + +task v4_hir_task_param_segment_span(hir_id: int, item_id: int, param_id: int) -> word { + pilot record_id = v4_hir_task_param_record_id(hir_id, item_id, param_id) + if record_id < 0 { give back V4_NO_SPAN } + give back array_get(v4_hir_task_param_segment_spans_handle(hir_id), record_id) +} + +task v4_hir_add_task_param_owner(hir_id: int, item_id: int, count: int) -> int { + pilot record_id = v4_hir_task_param_owner_record_count(hir_id) + array_push(v4_hir_task_param_owner_items_handle(hir_id), word_from_int(item_id)) + array_push(v4_hir_task_param_owner_counts_handle(hir_id), word_from_int(count)) + give back record_id +} + +task v4_hir_add_task_param(hir_id: int, item_id: int, ordinal: int, name: word, name_span: word, mode: word, lifetime_name: word, lifetime_span: word, type_text: word, type_span: word, segment_span: word) -> int { + pilot record_id = v4_hir_task_param_record_count(hir_id) + array_push(v4_hir_task_param_items_handle(hir_id), word_from_int(item_id)) + array_push(v4_hir_task_param_ordinals_handle(hir_id), word_from_int(ordinal)) + array_push(v4_hir_task_param_names_handle(hir_id), name) + array_push(v4_hir_task_param_name_spans_handle(hir_id), name_span) + array_push(v4_hir_task_param_modes_handle(hir_id), mode) + array_push(v4_hir_task_param_lifetimes_handle(hir_id), lifetime_name) + array_push(v4_hir_task_param_lifetime_spans_handle(hir_id), lifetime_span) + array_push(v4_hir_task_param_types_handle(hir_id), type_text) + array_push(v4_hir_task_param_type_spans_handle(hir_id), type_span) + array_push(v4_hir_task_param_segment_spans_handle(hir_id), segment_span) + give back record_id +} + task v4_hir_first_token_at_or_after(stream_id: int, offset: int) -> int { pilot token_id = 0 pilot token_count = v4_lex_token_count(stream_id) @@ -834,6 +1071,153 @@ task v4_hir_task_param_close_token(stream_id: int, open_token: int, end_token: i give back 0 - 1 } +task v4_hir_task_param_depth_after_token(depth: int, value: word) -> int { + if value == "(" or value == "[" or value == "{" or value == "<" { + give back depth + 1 + } + if value == ")" or value == "]" or value == "}" or value == ">" { + if depth > 0 { + give back depth - 1 + } + } + give back depth +} + +task v4_hir_task_param_find_colon(stream_id: int, start_token: int, end_token: int) -> int { + pilot idx = start_token + pilot depth = 0 + repeat until idx >= end_token { + if v4_lex_token_type(stream_id, idx) != v4_tok_trivia { + pilot value = v4_lex_token_value(stream_id, idx) + if value == ":" and depth == 0 { + give back idx + } + depth = v4_hir_task_param_depth_after_token(depth, value) + } + idx += 1 + } + give back 0 - 1 +} + +task v4_hir_task_param_add_error(hir_id: int, span: word, help: word) -> void { + v4_hir_add_diag(hir_id, v4_diag_new(v4_diag_error, span, "invalid ordinary task parameter declaration", help)) +} + +task v4_hir_lower_task_param_segment(hir_id: int, item_id: int, stream_id: int, start_token: int, end_token: int, ordinal: int) -> int { + pilot segment_span = v4_hir_span_from_tokens(stream_id, start_token, end_token) + pilot no_span = V4_NO_SPAN + if segment_span == no_span { + pilot item_span = v4_hir_item_span(hir_id, item_id) + v4_hir_task_param_add_error(hir_id, item_span, "remove the empty parameter segment or add name: Type") + give back 0 + } + + pilot colon = v4_hir_task_param_find_colon(stream_id, start_token, end_token) + if colon < 0 { + v4_hir_task_param_add_error(hir_id, segment_span, "ordinary task parameters require name: Type") + give back 0 + } + + pilot cursor = v4_hir_skip_trivia(stream_id, start_token, colon) + pilot mode = v4_hir_task_param_mode_value + pilot lifetime_name = "" + pilot lifetime_span = no_span + if cursor < colon and v4_lex_token_value(stream_id, cursor) == "lend" { + mode = v4_hir_task_param_mode_lend + cursor = v4_hir_skip_trivia(stream_id, cursor + 1, colon) + if cursor < colon and v4_lex_token_value(stream_id, cursor) == "mut" { + mode = v4_hir_task_param_mode_lend_mut + cursor = v4_hir_skip_trivia(stream_id, cursor + 1, colon) + } + if cursor < colon and v4_lex_token_type(stream_id, cursor) == v4_tok_lifetime { + pilot candidate_lifetime = v4_lex_token_value(stream_id, cursor) + if candidate_lifetime != "'_" { + lifetime_name = candidate_lifetime + lifetime_span = v4_lex_token_span(stream_id, cursor) + } + cursor = v4_hir_skip_trivia(stream_id, cursor + 1, colon) + } + } + + if cursor >= colon or v4_lex_token_type(stream_id, cursor) != v4_tok_ident { + v4_hir_task_param_add_error(hir_id, segment_span, "add one identifier before the parameter colon") + give back 0 + } + pilot name = v4_lex_token_value(stream_id, cursor) + pilot name_span = v4_lex_token_span(stream_id, cursor) + cursor = v4_hir_skip_trivia(stream_id, cursor + 1, colon) + if cursor != colon { + v4_hir_task_param_add_error(hir_id, segment_span, "keep only lend, optional mut/lifetime, and one name before the colon") + give back 0 + } + + pilot type_start = v4_hir_skip_trivia(stream_id, colon + 1, end_token) + if type_start >= end_token { + v4_hir_task_param_add_error(hir_id, segment_span, "add a parameter type after the colon") + give back 0 + } + pilot type_text = v4_hir_local_annotation_type_text(stream_id, type_start, end_token) + pilot type_span = v4_hir_span_from_tokens(stream_id, type_start, end_token) + if type_text == "" or type_span == no_span { + v4_hir_task_param_add_error(hir_id, segment_span, "add a complete parameter type after the colon") + give back 0 + } + + v4_hir_add_task_param(hir_id, item_id, ordinal, name, name_span, mode, lifetime_name, lifetime_span, type_text, type_span, segment_span) + give back 1 +} + +task v4_hir_lower_task_params(hir_id: int, item_id: int) -> void { + if not v4_hir_item_decl_is_ordinary_task(hir_id, item_id) { + give back + } + pilot stream_id = v4_hir_item_stream_id(hir_id) + if stream_id < 0 { + v4_hir_task_param_add_error(hir_id, v4_hir_item_span(hir_id, item_id), "the expanded task signature has no token stream") + v4_hir_add_task_param_owner(hir_id, item_id, 0) + give back + } + pilot item_span = v4_hir_item_span(hir_id, item_id) + pilot item_start = v4_hir_first_token_at_or_after(stream_id, v4_span_start(item_span)) + pilot item_end = v4_hir_first_token_at_or_after(stream_id, v4_span_end(item_span)) + pilot param_open = v4_hir_task_param_open_token(stream_id, item_start, item_end) + pilot param_close = v4_hir_task_param_close_token(stream_id, param_open, item_end) + if param_open < 0 or param_close < 0 { + v4_hir_task_param_add_error(hir_id, item_span, "add a complete (...) parameter list") + v4_hir_add_task_param_owner(hir_id, item_id, 0) + give back + } + + pilot first = v4_hir_skip_trivia(stream_id, param_open + 1, param_close) + if first >= param_close { + v4_hir_add_task_param_owner(hir_id, item_id, 0) + give back + } + + pilot valid_count = 0 + pilot segment_start = param_open + 1 + pilot depth = 0 + pilot idx = param_open + 1 + repeat until idx > param_close { + pilot at_end = idx == param_close + pilot separator = false + if not at_end and v4_lex_token_type(stream_id, idx) != v4_tok_trivia { + pilot value = v4_lex_token_value(stream_id, idx) + if value == "," and depth == 0 { + separator = true + } else { + depth = v4_hir_task_param_depth_after_token(depth, value) + } + } + if at_end or separator { + valid_count += v4_hir_lower_task_param_segment(hir_id, item_id, stream_id, segment_start, idx, valid_count) + segment_start = idx + 1 + } + idx += 1 + } + v4_hir_add_task_param_owner(hir_id, item_id, valid_count) +} + task v4_hir_task_return_type_end(stream_id: int, start_token: int, end_token: int) -> int { pilot idx = start_token pilot depth = 0 @@ -1153,6 +1537,7 @@ task v4_hir_lower_expanded(file_id: int, expansion_id: int) -> int { pilot item_span = v4_expand_node_span(expansion_id, node_idx) pilot item_id = v4_hir_add_item(hir_id, hir_kind, item_name, item_span, node_idx) v4_hir_lower_alias_target_type(hir_id, item_id, expansion_id, node_idx) + v4_hir_lower_task_params(hir_id, item_id) v4_hir_lower_task_return(hir_id, item_id) v4_hir_lower_local_annotations(hir_id, item_id) } @@ -1260,6 +1645,28 @@ task v4_hir_snapshot_task_return_total() -> int { give back total } +task v4_hir_snapshot_task_param_owner_total() -> int { + v4_hir_init() + pilot total = 0 + pilot hir_id = 0 + repeat until hir_id >= v4_hir_file_count() { + total += v4_hir_task_param_owner_record_count(hir_id) + hir_id += 1 + } + give back total +} + +task v4_hir_snapshot_task_param_total() -> int { + v4_hir_init() + pilot total = 0 + pilot hir_id = 0 + repeat until hir_id >= v4_hir_file_count() { + total += v4_hir_task_param_record_count(hir_id) + hir_id += 1 + } + give back total +} + task v4_hir_snapshot_diag_total() -> int { v4_hir_init() pilot total = 0 @@ -1279,6 +1686,8 @@ task v4_hir_snapshot_summary() -> word { summary = summary + " alias-targets=" + word_from_int(v4_hir_snapshot_alias_target_total()) summary = summary + " local-annotations=" + word_from_int(v4_hir_snapshot_local_annotation_total()) summary = summary + " task-returns=" + word_from_int(v4_hir_snapshot_task_return_total()) + summary = summary + " task-param-owners=" + word_from_int(v4_hir_snapshot_task_param_owner_total()) + summary = summary + " task-params=" + word_from_int(v4_hir_snapshot_task_param_total()) summary = summary + " diagnostics=" + word_from_int(v4_hir_snapshot_diag_total()) give back summary } @@ -1291,6 +1700,8 @@ task v4_hir_snapshot_header() -> word { out = out + "|alias-targets=" + word_from_int(v4_hir_snapshot_alias_target_total()) out = out + "|local-annotations=" + word_from_int(v4_hir_snapshot_local_annotation_total()) out = out + "|task-returns=" + word_from_int(v4_hir_snapshot_task_return_total()) + out = out + "|task-param-owners=" + word_from_int(v4_hir_snapshot_task_param_owner_total()) + out = out + "|task-params=" + word_from_int(v4_hir_snapshot_task_param_total()) out = out + "|diagnostics=" + word_from_int(v4_hir_snapshot_diag_total()) give back out } @@ -1343,6 +1754,32 @@ task v4_hir_snapshot_task_return_line(hir_id: int, record_id: int) -> word { give back out } +task v4_hir_snapshot_task_param_owner_line(hir_id: int, record_id: int) -> word { + pilot out = "hir-task-param-owner" + out = out + "|" + word_from_int(hir_id) + out = out + "|" + word_from_int(record_id) + out = out + "|" + array_get(v4_hir_task_param_owner_items_handle(hir_id), record_id) + out = out + "|" + array_get(v4_hir_task_param_owner_counts_handle(hir_id), record_id) + give back out +} + +task v4_hir_snapshot_task_param_line(hir_id: int, record_id: int) -> word { + pilot out = "hir-task-param" + out = out + "|" + word_from_int(hir_id) + out = out + "|" + word_from_int(record_id) + out = out + "|" + array_get(v4_hir_task_param_items_handle(hir_id), record_id) + out = out + "|" + array_get(v4_hir_task_param_ordinals_handle(hir_id), record_id) + out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_names_handle(hir_id), record_id)) + out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_name_spans_handle(hir_id), record_id)) + out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_modes_handle(hir_id), record_id)) + out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_lifetimes_handle(hir_id), record_id)) + out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_lifetime_spans_handle(hir_id), record_id)) + out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_types_handle(hir_id), record_id)) + out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_type_spans_handle(hir_id), record_id)) + out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_segment_spans_handle(hir_id), record_id)) + give back out +} + task v4_hir_snapshot_diag_line(hir_id: int, diag_id: int) -> word { pilot out = "hir-diag" out = out + "|" + word_from_int(hir_id) @@ -1384,6 +1821,22 @@ task v4_hir_snapshot() -> word { task_return_id += 1 } + pilot task_param_owner_id = 0 + pilot task_param_owner_count = v4_hir_task_param_owner_record_count(hir_id) + repeat until task_param_owner_id >= task_param_owner_count { + array_push(parts, "\n") + array_push(parts, v4_hir_snapshot_task_param_owner_line(hir_id, task_param_owner_id)) + task_param_owner_id += 1 + } + + pilot task_param_id = 0 + pilot task_param_count = v4_hir_task_param_record_count(hir_id) + repeat until task_param_id >= task_param_count { + array_push(parts, "\n") + array_push(parts, v4_hir_snapshot_task_param_line(hir_id, task_param_id)) + task_param_id += 1 + } + pilot diag_id = 0 pilot diag_count = v4_hir_diag_count(hir_id) repeat until diag_id >= diag_count { @@ -1400,7 +1853,7 @@ task v4_hir_snapshot() -> word { task v4_hir_snapshot_record_expected_fields(kind: word) -> int { if kind == "hir-snapshot" { - give back 8 + give back 10 } if kind == "hir" { give back 6 @@ -1414,6 +1867,12 @@ task v4_hir_snapshot_record_expected_fields(kind: word) -> int { if kind == "hir-task-return" { give back 7 } + if kind == "hir-task-param-owner" { + give back 5 + } + if kind == "hir-task-param" { + give back 13 + } if kind == "hir-diag" { give back 4 } @@ -1529,6 +1988,85 @@ task v4_hir_snapshot_task_return_is_valid(line: word) -> bool { give back v4_span_new(span_file, span_start, span_end) == type_span } +task v4_hir_snapshot_task_param_owner_is_valid(line: word) -> bool { + give back v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 1)) and v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 2)) and v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 3)) and v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 4)) +} + +task v4_hir_snapshot_span_is_canonical_nonempty(span: word) -> bool { + pilot no_span = V4_NO_SPAN + if span == no_span { + give back false + } + pilot file_id = v4_span_file(span) + pilot start_offset = v4_span_start(span) + pilot end_offset = v4_span_end(span) + if file_id == V4_NO_FILE or end_offset <= start_offset { + give back false + } + give back v4_span_new(file_id, start_offset, end_offset) == span +} + +task v4_hir_snapshot_span_is_contained(inner: word, outer: word) -> bool { + if v4_hir_snapshot_span_is_canonical_nonempty(inner) == false or v4_hir_snapshot_span_is_canonical_nonempty(outer) == false { + give back false + } + give back v4_span_file(inner) == v4_span_file(outer) and v4_span_start(inner) >= v4_span_start(outer) and v4_span_end(inner) <= v4_span_end(outer) +} + +task v4_hir_snapshot_named_lifetime_is_valid(lifetime_name: word) -> bool { + if lifetime_name.length() <= 1 or lifetime_name.char_at(0) != "'" or v4_lex_is_ident_start(lifetime_name.char_at(1)) == false { + give back false + } + pilot idx = 2 + repeat until idx >= lifetime_name.length() { + if v4_lex_is_ident_continue(lifetime_name.char_at(idx)) == false { + give back false + } + idx += 1 + } + give back true +} + +task v4_hir_snapshot_task_param_is_valid(line: word) -> bool { + if v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 1)) == false or v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 2)) == false or v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 3)) == false or v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 4)) == false { + give back false + } + pilot name = v4_hir_snapshot_field(line, 5) + pilot name_span = v4_hir_snapshot_field(line, 6) + pilot mode = v4_hir_snapshot_field(line, 7) + pilot lifetime_name = v4_hir_snapshot_field(line, 8) + pilot lifetime_span = v4_hir_snapshot_field(line, 9) + pilot type_text = v4_hir_snapshot_field(line, 10) + pilot type_span = v4_hir_snapshot_field(line, 11) + pilot segment_span = v4_hir_snapshot_field(line, 12) + pilot no_span = V4_NO_SPAN + if name == "" or type_text == "" { + give back false + } + if mode != v4_hir_task_param_mode_value and mode != v4_hir_task_param_mode_lend and mode != v4_hir_task_param_mode_lend_mut { + give back false + } + if mode == v4_hir_task_param_mode_value and (lifetime_name != "" or lifetime_span != no_span) { + give back false + } + if lifetime_name == "" { + if lifetime_span != no_span { + give back false + } + } else { + if mode == v4_hir_task_param_mode_value or lifetime_name == "'_" or v4_hir_snapshot_named_lifetime_is_valid(lifetime_name) == false { + give back false + } + if v4_hir_snapshot_span_is_contained(lifetime_span, segment_span) == false { + give back false + } + } + if v4_hir_snapshot_span_is_contained(name_span, segment_span) == false or v4_hir_snapshot_span_is_contained(type_span, segment_span) == false { + give back false + } + give back true +} + task v4_hir_snapshot_file_for_hir(payload: word, wanted_hir_id: word) -> word { pilot found_file = V4_NO_FILE pilot matches = 0 @@ -1642,6 +2180,71 @@ task v4_hir_snapshot_task_return_owner_is_valid(payload: word, line: word) -> bo give back matches == 1 } +task v4_hir_snapshot_task_param_owner_owner_is_valid(payload: word, line: word) -> bool { + pilot wanted_hir_id = v4_hir_snapshot_field_raw(line, 1) + pilot wanted_item_id = v4_hir_snapshot_field_raw(line, 3) + pilot matches = 0 + pilot line_id = 0 + pilot line_count = v4_hir_snapshot_line_count(payload) + repeat until line_id >= line_count { + pilot candidate = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(candidate, 0) == "hir-item" and v4_hir_snapshot_field_raw(candidate, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(candidate, 2) == wanted_item_id { + if v4_hir_snapshot_field(candidate, 3) != v4_hir_task { + give back false + } + matches += 1 + } + line_id += 1 + } + give back matches == 1 +} + +task v4_hir_snapshot_task_param_owner_is_present(payload: word, wanted_hir_id: word, wanted_item_id: word) -> bool { + pilot matches = 0 + pilot line_id = 0 + pilot line_count = v4_hir_snapshot_line_count(payload) + repeat until line_id >= line_count { + pilot candidate = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(candidate, 0) == "hir-task-param-owner" and v4_hir_snapshot_field_raw(candidate, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(candidate, 3) == wanted_item_id { + matches += 1 + } + line_id += 1 + } + give back matches == 1 +} + +task v4_hir_snapshot_task_param_owner_for_child_is_valid(payload: word, line: word) -> bool { + pilot wanted_hir_id = v4_hir_snapshot_field_raw(line, 1) + pilot wanted_item_id = v4_hir_snapshot_field_raw(line, 3) + pilot no_file = V4_NO_FILE + if v4_hir_snapshot_task_param_owner_is_present(payload, wanted_hir_id, wanted_item_id) == false { + give back false + } + pilot snapshot_file = v4_hir_snapshot_file_for_hir(payload, wanted_hir_id) + if snapshot_file == no_file { + give back false + } + pilot matches = 0 + pilot line_id = 0 + pilot line_count = v4_hir_snapshot_line_count(payload) + repeat until line_id >= line_count { + pilot candidate = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(candidate, 0) == "hir-item" and v4_hir_snapshot_field_raw(candidate, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(candidate, 2) == wanted_item_id { + if v4_hir_snapshot_field(candidate, 3) != v4_hir_task { + give back false + } + pilot item_span = v4_hir_snapshot_field(candidate, 6) + pilot segment_span = v4_hir_snapshot_field(line, 12) + if v4_span_file(item_span) != snapshot_file or v4_hir_snapshot_span_is_contained(segment_span, item_span) == false { + give back false + } + matches += 1 + } + line_id += 1 + } + give back matches == 1 +} + task v4_hir_snapshot_local_annotation_slots_are_valid(payload: word, hir_line: word) -> bool { pilot wanted_hir_id = v4_hir_snapshot_field_raw(hir_line, 1) pilot declared_items = word_to_int(v4_hir_snapshot_field_raw(hir_line, 4)) @@ -1739,6 +2342,125 @@ task v4_hir_snapshot_task_return_slots_are_valid(payload: word, hir_line: word) give back true } +task v4_hir_snapshot_task_param_slots_are_valid(payload: word, hir_line: word) -> bool { + pilot wanted_hir_id = v4_hir_snapshot_field_raw(hir_line, 1) + pilot declared_items = word_to_int(v4_hir_snapshot_field_raw(hir_line, 4)) + pilot owner_count = 0 + pilot param_count = 0 + pilot line_id = 0 + pilot line_count = v4_hir_snapshot_line_count(payload) + repeat until line_id >= line_count { + pilot line = v4_hir_snapshot_line(payload, line_id) + pilot kind = v4_hir_snapshot_field_raw(line, 0) + if kind == "hir-task-param-owner" and v4_hir_snapshot_field_raw(line, 1) == wanted_hir_id { + owner_count += 1 + } else if kind == "hir-task-param" and v4_hir_snapshot_field_raw(line, 1) == wanted_hir_id { + param_count += 1 + } + line_id += 1 + } + + pilot expected_record = 0 + repeat until expected_record >= owner_count { + pilot occurrences = 0 + line_id = 0 + repeat until line_id >= line_count { + pilot line = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(line, 0) == "hir-task-param-owner" and v4_hir_snapshot_field_raw(line, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(line, 2) == word_from_int(expected_record) { + pilot item_id = word_to_int(v4_hir_snapshot_field_raw(line, 3)) + if item_id < 0 or item_id >= declared_items { + give back false + } + occurrences += 1 + } + line_id += 1 + } + if occurrences != 1 { give back false } + expected_record += 1 + } + + expected_record = 0 + repeat until expected_record >= param_count { + pilot occurrences = 0 + line_id = 0 + repeat until line_id >= line_count { + pilot line = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(line, 0) == "hir-task-param" and v4_hir_snapshot_field_raw(line, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(line, 2) == word_from_int(expected_record) { + pilot item_id = word_to_int(v4_hir_snapshot_field_raw(line, 3)) + if item_id < 0 or item_id >= declared_items { + give back false + } + occurrences += 1 + } + line_id += 1 + } + if occurrences != 1 { give back false } + expected_record += 1 + } + + pilot item_id = 0 + repeat until item_id >= declared_items { + pilot item_kind = "" + pilot owner_records = 0 + line_id = 0 + repeat until line_id >= line_count { + pilot line = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(line, 0) == "hir-item" and v4_hir_snapshot_field_raw(line, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(line, 2) == word_from_int(item_id) { + item_kind = v4_hir_snapshot_field(line, 3) + } else if v4_hir_snapshot_field_raw(line, 0) == "hir-task-param-owner" and v4_hir_snapshot_field_raw(line, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(line, 3) == word_from_int(item_id) { + owner_records += 1 + } + line_id += 1 + } + if item_kind == v4_hir_task and owner_records != 1 { give back false } + if item_kind != v4_hir_task and owner_records != 0 { give back false } + item_id += 1 + } + + pilot owner_id = 0 + repeat until owner_id >= owner_count { + pilot owner_line = "" + line_id = 0 + repeat until line_id >= line_count { + pilot candidate = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(candidate, 0) == "hir-task-param-owner" and v4_hir_snapshot_field_raw(candidate, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(candidate, 2) == word_from_int(owner_id) { + owner_line = candidate + } + line_id += 1 + } + if owner_line == "" { give back false } + pilot owner_item = v4_hir_snapshot_field_raw(owner_line, 3) + pilot declared_count = word_to_int(v4_hir_snapshot_field_raw(owner_line, 4)) + pilot actual_count = 0 + line_id = 0 + repeat until line_id >= line_count { + pilot child = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(child, 0) == "hir-task-param" and v4_hir_snapshot_field_raw(child, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(child, 3) == owner_item { + actual_count += 1 + } + line_id += 1 + } + if actual_count != declared_count { give back false } + + pilot ordinal = 0 + repeat until ordinal >= declared_count { + pilot occurrences = 0 + line_id = 0 + repeat until line_id >= line_count { + pilot child = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(child, 0) == "hir-task-param" and v4_hir_snapshot_field_raw(child, 1) == wanted_hir_id and v4_hir_snapshot_field_raw(child, 3) == owner_item and v4_hir_snapshot_field_raw(child, 4) == word_from_int(ordinal) { + occurrences += 1 + } + line_id += 1 + } + if occurrences != 1 { give back false } + ordinal += 1 + } + owner_id += 1 + } + give back true +} + task v4_hir_snapshot_child_slots_are_valid(payload: word, hir_line: word) -> bool { pilot wanted_hir_id = v4_hir_snapshot_field_raw(hir_line, 1) pilot declared_items_word = v4_hir_snapshot_field_raw(hir_line, 4) @@ -1845,6 +2567,12 @@ task v4_hir_snapshot_record_is_valid(line: word) -> bool { if kind == "hir-task-return" and v4_hir_snapshot_task_return_is_valid(line) == false { give back false } + if kind == "hir-task-param-owner" and v4_hir_snapshot_task_param_owner_is_valid(line) == false { + give back false + } + if kind == "hir-task-param" and v4_hir_snapshot_task_param_is_valid(line) == false { + give back false + } give back true } @@ -1855,6 +2583,8 @@ task v4_hir_snapshot_validate(payload: word) -> word { pilot alias_targets = 0 pilot local_annotations = 0 pilot task_returns = 0 + pilot task_param_owners = 0 + pilot task_params = 0 pilot diagnostics = 0 pilot malformed = 0 pilot saw_header = 0 @@ -1865,6 +2595,8 @@ task v4_hir_snapshot_validate(payload: word) -> word { pilot declared_alias_targets = "" pilot declared_local_annotations = "" pilot declared_task_returns = "" + pilot declared_task_param_owners = "" + pilot declared_task_params = "" pilot declared_diagnostics = "" pilot no_file = V4_NO_FILE @@ -1883,6 +2615,8 @@ task v4_hir_snapshot_validate(payload: word) -> word { declared_alias_targets = v4_hir_snapshot_key_value(line, "alias-targets") declared_local_annotations = v4_hir_snapshot_key_value(line, "local-annotations") declared_task_returns = v4_hir_snapshot_key_value(line, "task-returns") + declared_task_param_owners = v4_hir_snapshot_key_value(line, "task-param-owners") + declared_task_params = v4_hir_snapshot_key_value(line, "task-params") declared_diagnostics = v4_hir_snapshot_key_value(line, "diagnostics") if format != v4_hir_snapshot_format { malformed += 1 @@ -1898,6 +2632,9 @@ task v4_hir_snapshot_validate(payload: word) -> word { if v4_hir_snapshot_task_return_slots_are_valid(payload, line) == false { malformed += 1 } + if v4_hir_snapshot_task_param_slots_are_valid(payload, line) == false { + malformed += 1 + } } else if kind == "hir-item" { items += 1 if v4_hir_snapshot_file_for_hir(payload, v4_hir_snapshot_field_raw(line, 1)) == no_file { @@ -1919,6 +2656,16 @@ task v4_hir_snapshot_validate(payload: word) -> word { if v4_hir_snapshot_task_return_owner_is_valid(payload, line) == false { malformed += 1 } + } else if kind == "hir-task-param-owner" { + task_param_owners += 1 + if v4_hir_snapshot_task_param_owner_owner_is_valid(payload, line) == false { + malformed += 1 + } + } else if kind == "hir-task-param" { + task_params += 1 + if v4_hir_snapshot_task_param_owner_for_child_is_valid(payload, line) == false { + malformed += 1 + } } else if kind == "hir-diag" { diagnostics += 1 if v4_hir_snapshot_file_for_hir(payload, v4_hir_snapshot_field_raw(line, 1)) == no_file { @@ -1956,6 +2703,12 @@ task v4_hir_snapshot_validate(payload: word) -> word { if declared_task_returns != word_from_int(task_returns) { import_ok = 0 } + if declared_task_param_owners != word_from_int(task_param_owners) { + import_ok = 0 + } + if declared_task_params != word_from_int(task_params) { + import_ok = 0 + } if v4_hir_snapshot_hir_slots_are_valid(payload, files) == false { import_ok = 0 } @@ -1972,6 +2725,10 @@ task v4_hir_snapshot_validate(payload: word) -> word { out = out + " declared-local-annotations=" + declared_local_annotations out = out + " task-returns=" + word_from_int(task_returns) out = out + " declared-task-returns=" + declared_task_returns + out = out + " task-param-owners=" + word_from_int(task_param_owners) + out = out + " declared-task-param-owners=" + declared_task_param_owners + out = out + " task-params=" + word_from_int(task_params) + out = out + " declared-task-params=" + declared_task_params out = out + " diagnostics=" + word_from_int(diagnostics) out = out + " malformed=" + word_from_int(malformed) out = out + " headers=" + word_from_int(saw_header) @@ -1999,6 +2756,18 @@ task v4_hir_restore_file_slot(hir_id: int, file_id: int, expansion_id: int) -> i array_push(v4_hir_task_return_forms, word_from_int(array_new())) array_push(v4_hir_task_return_types, word_from_int(array_new())) array_push(v4_hir_task_return_spans, word_from_int(array_new())) + array_push(v4_hir_task_param_owner_items, word_from_int(array_new())) + array_push(v4_hir_task_param_owner_counts, word_from_int(array_new())) + array_push(v4_hir_task_param_items, word_from_int(array_new())) + array_push(v4_hir_task_param_ordinals, word_from_int(array_new())) + array_push(v4_hir_task_param_names, word_from_int(array_new())) + array_push(v4_hir_task_param_name_spans, word_from_int(array_new())) + array_push(v4_hir_task_param_modes, word_from_int(array_new())) + array_push(v4_hir_task_param_lifetimes, word_from_int(array_new())) + array_push(v4_hir_task_param_lifetime_spans, word_from_int(array_new())) + array_push(v4_hir_task_param_types, word_from_int(array_new())) + array_push(v4_hir_task_param_type_spans, word_from_int(array_new())) + array_push(v4_hir_task_param_segment_spans, word_from_int(array_new())) array_push(v4_hir_diags, word_from_int(array_new())) } @@ -2019,6 +2788,18 @@ task v4_hir_restore_file_slot(hir_id: int, file_id: int, expansion_id: int) -> i array_set(v4_hir_task_return_forms, hir_id, word_from_int(array_new())) array_set(v4_hir_task_return_types, hir_id, word_from_int(array_new())) array_set(v4_hir_task_return_spans, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_owner_items, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_owner_counts, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_items, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_ordinals, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_names, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_name_spans, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_modes, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_lifetimes, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_lifetime_spans, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_types, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_type_spans, hir_id, word_from_int(array_new())) + array_set(v4_hir_task_param_segment_spans, hir_id, word_from_int(array_new())) array_set(v4_hir_diags, hir_id, word_from_int(array_new())) if hir_id >= v4_hir_file_len { v4_hir_file_len = hir_id + 1 @@ -2159,6 +2940,62 @@ task v4_hir_snapshot_restore_task_return_line(line: word) -> int { give back v4_hir_restore_task_return_slot(hir_id, record_id, item_id, form, type_text, type_span) } +task v4_hir_restore_task_param_owner_slot(hir_id: int, record_id: int, item_id: int, count: int) -> int { + if v4_hir_file_exists(hir_id) == false { + give back 0 + } + repeat until v4_hir_task_param_owner_record_count(hir_id) > record_id { + array_push(v4_hir_task_param_owner_items_handle(hir_id), word_from_int(0 - 1)) + array_push(v4_hir_task_param_owner_counts_handle(hir_id), "0") + } + array_set(v4_hir_task_param_owner_items_handle(hir_id), record_id, word_from_int(item_id)) + array_set(v4_hir_task_param_owner_counts_handle(hir_id), record_id, word_from_int(count)) + give back 1 +} + +task v4_hir_snapshot_restore_task_param_owner_line(line: word) -> int { + if v4_hir_snapshot_record_is_valid(line) == false or v4_hir_snapshot_field_raw(line, 0) != "hir-task-param-owner" { + give back 0 + } + give back v4_hir_restore_task_param_owner_slot(word_to_int(v4_hir_snapshot_field_raw(line, 1)), word_to_int(v4_hir_snapshot_field_raw(line, 2)), word_to_int(v4_hir_snapshot_field_raw(line, 3)), word_to_int(v4_hir_snapshot_field_raw(line, 4))) +} + +task v4_hir_restore_task_param_slot(hir_id: int, record_id: int, item_id: int, ordinal: int, name: word, name_span: word, mode: word, lifetime_name: word, lifetime_span: word, type_text: word, type_span: word, segment_span: word) -> int { + if v4_hir_file_exists(hir_id) == false { + give back 0 + } + repeat until v4_hir_task_param_record_count(hir_id) > record_id { + array_push(v4_hir_task_param_items_handle(hir_id), word_from_int(0 - 1)) + array_push(v4_hir_task_param_ordinals_handle(hir_id), word_from_int(0 - 1)) + array_push(v4_hir_task_param_names_handle(hir_id), "") + array_push(v4_hir_task_param_name_spans_handle(hir_id), V4_NO_SPAN) + array_push(v4_hir_task_param_modes_handle(hir_id), "") + array_push(v4_hir_task_param_lifetimes_handle(hir_id), "") + array_push(v4_hir_task_param_lifetime_spans_handle(hir_id), V4_NO_SPAN) + array_push(v4_hir_task_param_types_handle(hir_id), "") + array_push(v4_hir_task_param_type_spans_handle(hir_id), V4_NO_SPAN) + array_push(v4_hir_task_param_segment_spans_handle(hir_id), V4_NO_SPAN) + } + array_set(v4_hir_task_param_items_handle(hir_id), record_id, word_from_int(item_id)) + array_set(v4_hir_task_param_ordinals_handle(hir_id), record_id, word_from_int(ordinal)) + array_set(v4_hir_task_param_names_handle(hir_id), record_id, name) + array_set(v4_hir_task_param_name_spans_handle(hir_id), record_id, name_span) + array_set(v4_hir_task_param_modes_handle(hir_id), record_id, mode) + array_set(v4_hir_task_param_lifetimes_handle(hir_id), record_id, lifetime_name) + array_set(v4_hir_task_param_lifetime_spans_handle(hir_id), record_id, lifetime_span) + array_set(v4_hir_task_param_types_handle(hir_id), record_id, type_text) + array_set(v4_hir_task_param_type_spans_handle(hir_id), record_id, type_span) + array_set(v4_hir_task_param_segment_spans_handle(hir_id), record_id, segment_span) + give back 1 +} + +task v4_hir_snapshot_restore_task_param_line(line: word) -> int { + if v4_hir_snapshot_record_is_valid(line) == false or v4_hir_snapshot_field_raw(line, 0) != "hir-task-param" { + give back 0 + } + give back v4_hir_restore_task_param_slot(word_to_int(v4_hir_snapshot_field_raw(line, 1)), word_to_int(v4_hir_snapshot_field_raw(line, 2)), word_to_int(v4_hir_snapshot_field_raw(line, 3)), word_to_int(v4_hir_snapshot_field_raw(line, 4)), v4_hir_snapshot_field(line, 5), v4_hir_snapshot_field(line, 6), v4_hir_snapshot_field(line, 7), v4_hir_snapshot_field(line, 8), v4_hir_snapshot_field(line, 9), v4_hir_snapshot_field(line, 10), v4_hir_snapshot_field(line, 11), v4_hir_snapshot_field(line, 12)) +} + task v4_hir_snapshot_restore_diag_line(line: word) -> int { if v4_hir_snapshot_record_is_valid(line) == false { give back 0 @@ -2187,6 +3024,8 @@ task v4_hir_snapshot_restore(payload: word) -> word { pilot restored_items = 0 pilot restored_local_annotations = 0 pilot restored_task_returns = 0 + pilot restored_task_param_owners = 0 + pilot restored_task_params = 0 pilot restored_diagnostics = 0 pilot skipped_other = 0 v4_hir_begin_snapshot_restore() @@ -2199,7 +3038,7 @@ task v4_hir_snapshot_restore(payload: word) -> word { pilot kind = v4_hir_snapshot_field_raw(line, 0) if kind == "hir" { restored_files += v4_hir_snapshot_restore_file_line(line) - } else if kind != "hir-item" and kind != "hir-local-annotation" and kind != "hir-task-return" and kind != "hir-diag" and kind != "hir-snapshot" and kind != "end" { + } else if kind != "hir-item" and kind != "hir-local-annotation" and kind != "hir-task-return" and kind != "hir-task-param-owner" and kind != "hir-task-param" and kind != "hir-diag" and kind != "hir-snapshot" and kind != "end" { skipped_other += 1 } } @@ -2217,6 +3056,10 @@ task v4_hir_snapshot_restore(payload: word) -> word { restored_local_annotations += v4_hir_snapshot_restore_local_annotation_line(line) } else if kind == "hir-task-return" { restored_task_returns += v4_hir_snapshot_restore_task_return_line(line) + } else if kind == "hir-task-param-owner" { + restored_task_param_owners += v4_hir_snapshot_restore_task_param_owner_line(line) + } else if kind == "hir-task-param" { + restored_task_params += v4_hir_snapshot_restore_task_param_line(line) } else if kind == "hir-diag" { restored_diagnostics += v4_hir_snapshot_restore_diag_line(line) } @@ -2229,6 +3072,8 @@ task v4_hir_snapshot_restore(payload: word) -> word { out = out + " items=" + word_from_int(restored_items) out = out + " local-annotations=" + word_from_int(restored_local_annotations) out = out + " task-returns=" + word_from_int(restored_task_returns) + out = out + " task-param-owners=" + word_from_int(restored_task_param_owners) + out = out + " task-params=" + word_from_int(restored_task_params) out = out + " diagnostics=" + word_from_int(restored_diagnostics) out = out + " skipped-other=" + word_from_int(skipped_other) out = out + " live-files=" + word_from_int(v4_hir_file_count()) diff --git a/src/compiler/v4/crates/freak_mir_build/src/lib.fk b/src/compiler/v4/crates/freak_mir_build/src/lib.fk index 1d235dc9..861971d9 100644 --- a/src/compiler/v4/crates/freak_mir_build/src/lib.fk +++ b/src/compiler/v4/crates/freak_mir_build/src/lib.fk @@ -8653,12 +8653,17 @@ task v4_mir_seed_param_local(mir_id: int, body_id: int, param_name: word, param_ task v4_mir_seed_signature_params(mir_id: int, body_id: int, ty_id: int, sig_id: int, item_span: word) -> void { pilot param_idx = 0 pilot param_count = v4_ty_signature_param_count(ty_id, sig_id) + pilot no_span = V4_NO_SPAN repeat until param_idx >= param_count { pilot param_name = v4_ty_signature_param_name(ty_id, sig_id, param_idx) if param_name != "" { pilot param_ty = v4_ty_signature_param_type(ty_id, sig_id, param_idx) pilot param_mode = v4_ty_signature_param_mode(ty_id, sig_id, param_idx) - v4_mir_seed_param_local(mir_id, body_id, param_name, param_ty, param_mode, item_span, "this signature") + pilot param_span = v4_ty_signature_param_segment_span(ty_id, sig_id, param_idx) + if param_span == no_span { + param_span = item_span + } + v4_mir_seed_param_local(mir_id, body_id, param_name, param_ty, param_mode, param_span, "this signature") } param_idx += 1 } diff --git a/src/compiler/v4/crates/freak_ty/src/lib.fk b/src/compiler/v4/crates/freak_ty/src/lib.fk index 479abaef..1e6dbb9f 100644 --- a/src/compiler/v4/crates/freak_ty/src/lib.fk +++ b/src/compiler/v4/crates/freak_ty/src/lib.fk @@ -4243,7 +4243,7 @@ task v4_ty_find_matching_angle(stream_id: int, open_token: int, end_token: int) give back 0 - 1 } -task v4_ty_signature_param_open_token(ty_id: int, sig_id: int) -> int { +task v4_ty_nonordinary_signature_param_open_token_fallback(ty_id: int, sig_id: int) -> int { pilot stream_id = v4_ty_signature_stream_id(ty_id) if stream_id < 0 { give back 0 - 1 @@ -4256,9 +4256,9 @@ task v4_ty_signature_param_open_token(ty_id: int, sig_id: int) -> int { give back v4_ty_find_token_value(stream_id, start_token, end_token, "(") } -task v4_ty_signature_param_close_token(ty_id: int, sig_id: int) -> int { +task v4_ty_nonordinary_signature_param_close_token_fallback(ty_id: int, sig_id: int) -> int { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot open_token = v4_ty_signature_param_open_token(ty_id, sig_id) + pilot open_token = v4_ty_nonordinary_signature_param_open_token_fallback(ty_id, sig_id) if stream_id < 0 or open_token < 0 { give back 0 - 1 } @@ -4376,13 +4376,20 @@ task v4_ty_signature_generic_count(ty_id: int, sig_id: int) -> int { give back v4_ty_param_count_from_tokens(stream_id, open_token, close_token) } -task v4_ty_signature_param_count(ty_id: int, sig_id: int) -> int { +task v4_ty_nonordinary_signature_param_count_fallback(ty_id: int, sig_id: int) -> int { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot open_token = v4_ty_signature_param_open_token(ty_id, sig_id) - pilot close_token = v4_ty_signature_param_close_token(ty_id, sig_id) + pilot open_token = v4_ty_nonordinary_signature_param_open_token_fallback(ty_id, sig_id) + pilot close_token = v4_ty_nonordinary_signature_param_close_token_fallback(ty_id, sig_id) give back v4_ty_param_count_from_tokens(stream_id, open_token, close_token) } +task v4_ty_signature_param_count(ty_id: int, sig_id: int) -> int { + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_count(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id)) + } + give back v4_ty_nonordinary_signature_param_count_fallback(ty_id, sig_id) +} + task v4_ty_is_variadic_param_surface(type_text: word) -> bool { give back v4_ty_trim_spaces(type_text) == "..." } @@ -4414,10 +4421,10 @@ task v4_ty_param_count_from_tokens(stream_id: int, open_token: int, close_token: give back count } -task v4_ty_signature_param_segment_start(ty_id: int, sig_id: int, param_id: int) -> int { +task v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id: int, sig_id: int, param_id: int) -> int { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot open_token = v4_ty_signature_param_open_token(ty_id, sig_id) - pilot close_token = v4_ty_signature_param_close_token(ty_id, sig_id) + pilot open_token = v4_ty_nonordinary_signature_param_open_token_fallback(ty_id, sig_id) + pilot close_token = v4_ty_nonordinary_signature_param_close_token_fallback(ty_id, sig_id) give back v4_ty_param_segment_start_from_tokens(stream_id, open_token, close_token, param_id) } @@ -4451,10 +4458,10 @@ task v4_ty_param_segment_start_from_tokens(stream_id: int, open_token: int, clos give back 0 - 1 } -task v4_ty_signature_param_segment_end(ty_id: int, sig_id: int, param_id: int) -> int { +task v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id: int, sig_id: int, param_id: int) -> int { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - pilot close_token = v4_ty_signature_param_close_token(ty_id, sig_id) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot close_token = v4_ty_nonordinary_signature_param_close_token_fallback(ty_id, sig_id) give back v4_ty_param_segment_end_from_tokens(stream_id, start_token, close_token) } @@ -4889,13 +4896,7 @@ task v4_ty_signature_lifetime_outlives_ids(ty_id: int, sig_id: int, longer_gener } task v4_ty_signature_is_ordinary_static_task(ty_id: int, sig_id: int) -> bool { - if sig_id < 0 or sig_id >= v4_ty_signature_count(ty_id) { - give back false - } - if v4_ty_signature_kind(ty_id, sig_id) != v4_ty_task_sig { - give back false - } - give back v4_ty_signature_extern_member_id(ty_id, sig_id) < 0 + give back v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) } task v4_ty_signature_lifetime_outlives(ty_id: int, sig_id: int, longer_name: word, shorter_name: word) -> bool { @@ -4919,13 +4920,20 @@ task v4_ty_signature_lifetime_outlives(ty_id: int, sig_id: int, longer_name: wor give back v4_ty_signature_lifetime_outlives_ids(ty_id, sig_id, longer_generic_id, shorter_generic_id) } -task v4_ty_signature_param_name(ty_id: int, sig_id: int, param_id: int) -> word { +task v4_ty_nonordinary_signature_param_name_fallback(ty_id: int, sig_id: int, param_id: int) -> word { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - pilot end_token = v4_ty_signature_param_segment_end(ty_id, sig_id, param_id) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot end_token = v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id, sig_id, param_id) give back v4_ty_param_name_from_tokens(stream_id, start_token, end_token) } +task v4_ty_signature_param_name(ty_id: int, sig_id: int, param_id: int) -> word { + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_name(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id), param_id) + } + give back v4_ty_nonordinary_signature_param_name_fallback(ty_id, sig_id, param_id) +} + task v4_ty_signature_param_index_for_name(ty_id: int, sig_id: int, wanted_name: word) -> int { pilot param_idx = 0 pilot param_count = v4_ty_signature_param_count(ty_id, sig_id) @@ -5027,24 +5035,38 @@ task v4_ty_param_contract_prefix(mode: word, lifetime_name: word) -> word { give back out } -task v4_ty_signature_param_mode(ty_id: int, sig_id: int, param_id: int) -> word { +task v4_ty_nonordinary_signature_param_mode_fallback(ty_id: int, sig_id: int, param_id: int) -> word { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - pilot end_token = v4_ty_signature_param_segment_end(ty_id, sig_id, param_id) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot end_token = v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id, sig_id, param_id) give back v4_ty_param_mode_from_tokens(stream_id, start_token, end_token) } -task v4_ty_signature_param_lifetime(ty_id: int, sig_id: int, param_id: int) -> word { +task v4_ty_signature_param_mode(ty_id: int, sig_id: int, param_id: int) -> word { + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_mode(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id), param_id) + } + give back v4_ty_nonordinary_signature_param_mode_fallback(ty_id, sig_id, param_id) +} + +task v4_ty_nonordinary_signature_param_lifetime_fallback(ty_id: int, sig_id: int, param_id: int) -> word { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - pilot end_token = v4_ty_signature_param_segment_end(ty_id, sig_id, param_id) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot end_token = v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id, sig_id, param_id) give back v4_ty_param_lifetime_from_tokens(stream_id, start_token, end_token) } -task v4_ty_signature_param_lifetime_span(ty_id: int, sig_id: int, param_id: int) -> word { +task v4_ty_signature_param_lifetime(ty_id: int, sig_id: int, param_id: int) -> word { + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_lifetime(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id), param_id) + } + give back v4_ty_nonordinary_signature_param_lifetime_fallback(ty_id, sig_id, param_id) +} + +task v4_ty_nonordinary_signature_param_lifetime_span_fallback(ty_id: int, sig_id: int, param_id: int) -> word { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - pilot end_token = v4_ty_signature_param_segment_end(ty_id, sig_id, param_id) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot end_token = v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id, sig_id, param_id) pilot lifetime_token = v4_ty_param_lifetime_token_from_tokens(stream_id, start_token, end_token) if lifetime_token < 0 { give back V4_NO_SPAN @@ -5052,6 +5074,13 @@ task v4_ty_signature_param_lifetime_span(ty_id: int, sig_id: int, param_id: int) give back v4_ty_span_from_tokens(stream_id, lifetime_token, lifetime_token + 1) } +task v4_ty_signature_param_lifetime_span(ty_id: int, sig_id: int, param_id: int) -> word { + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_lifetime_span(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id), param_id) + } + give back v4_ty_nonordinary_signature_param_lifetime_span_fallback(ty_id, sig_id, param_id) +} + task v4_ty_param_type_span_from_tokens(stream_id: int, start_token: int, end_token: int) -> word { if stream_id < 0 or start_token < 0 or end_token <= start_token { give back V4_NO_SPAN @@ -5068,21 +5097,26 @@ task v4_ty_param_type_span_from_tokens(stream_id: int, start_token: int, end_tok give back v4_ty_span_from_tokens(stream_id, type_start, end_token) } -task v4_ty_signature_param_type(ty_id: int, sig_id: int, param_id: int) -> word { +task v4_ty_nonordinary_signature_param_surface_type_fallback(ty_id: int, sig_id: int, param_id: int) -> word { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - pilot end_token = v4_ty_signature_param_segment_end(ty_id, sig_id, param_id) - if v4_ty_is_variadic_param_surface(v4_ty_param_type_from_tokens(stream_id, start_token, end_token)) { - give back v4_ty_unknown - } - give back v4_ty_canonical_type_in_signature(ty_id, sig_id, v4_ty_param_type_from_tokens(stream_id, start_token, end_token)) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot end_token = v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id, sig_id, param_id) + give back v4_ty_param_type_from_tokens(stream_id, start_token, end_token) } task v4_ty_signature_param_surface_type(ty_id: int, sig_id: int, param_id: int) -> word { - pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - pilot end_token = v4_ty_signature_param_segment_end(ty_id, sig_id, param_id) - give back v4_ty_param_type_from_tokens(stream_id, start_token, end_token) + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_surface_type(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id), param_id) + } + give back v4_ty_nonordinary_signature_param_surface_type_fallback(ty_id, sig_id, param_id) +} + +task v4_ty_signature_param_type(ty_id: int, sig_id: int, param_id: int) -> word { + pilot surface_type = v4_ty_signature_param_surface_type(ty_id, sig_id, param_id) + if v4_ty_is_variadic_param_surface(surface_type) { + give back v4_ty_unknown + } + give back v4_ty_canonical_type_in_signature(ty_id, sig_id, surface_type) } task v4_ty_signature_function_value_type(ty_id: int, sig_id: int) -> word { @@ -5127,13 +5161,53 @@ task v4_ty_signature_function_value_type(ty_id: int, sig_id: int) -> word { give back out + return_surface } -task v4_ty_signature_param_type_span(ty_id: int, sig_id: int, param_id: int) -> word { +task v4_ty_nonordinary_signature_param_type_span_fallback(ty_id: int, sig_id: int, param_id: int) -> word { pilot stream_id = v4_ty_signature_stream_id(ty_id) - pilot start_token = v4_ty_signature_param_segment_start(ty_id, sig_id, param_id) - pilot end_token = v4_ty_signature_param_segment_end(ty_id, sig_id, param_id) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot end_token = v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id, sig_id, param_id) give back v4_ty_param_type_span_from_tokens(stream_id, start_token, end_token) } +task v4_ty_signature_param_type_span(ty_id: int, sig_id: int, param_id: int) -> word { + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_type_span(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id), param_id) + } + give back v4_ty_nonordinary_signature_param_type_span_fallback(ty_id, sig_id, param_id) +} + +task v4_ty_nonordinary_signature_param_segment_span_fallback(ty_id: int, sig_id: int, param_id: int) -> word { + pilot stream_id = v4_ty_signature_stream_id(ty_id) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot end_token = v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id, sig_id, param_id) + give back v4_ty_span_from_tokens(stream_id, start_token, end_token) +} + +task v4_ty_signature_param_segment_span(ty_id: int, sig_id: int, param_id: int) -> word { + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_segment_span(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id), param_id) + } + give back v4_ty_nonordinary_signature_param_segment_span_fallback(ty_id, sig_id, param_id) +} + +task v4_ty_nonordinary_signature_param_name_span_fallback(ty_id: int, sig_id: int, param_id: int) -> word { + pilot stream_id = v4_ty_signature_stream_id(ty_id) + pilot start_token = v4_ty_nonordinary_signature_param_segment_start_fallback(ty_id, sig_id, param_id) + pilot end_token = v4_ty_nonordinary_signature_param_segment_end_fallback(ty_id, sig_id, param_id) + pilot param_name = v4_ty_nonordinary_signature_param_name_fallback(ty_id, sig_id, param_id) + pilot name_token = v4_ty_find_token_value(stream_id, start_token, end_token, param_name) + if stream_id < 0 or name_token < 0 or name_token >= end_token { + give back V4_NO_SPAN + } + give back v4_lex_token_span(stream_id, name_token) +} + +task v4_ty_signature_param_name_span(ty_id: int, sig_id: int, param_id: int) -> word { + if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id) { + give back v4_hir_task_param_name_span(v4_ty_signature_hir_id(ty_id), v4_ty_signature_hir_item(ty_id, sig_id), param_id) + } + give back v4_ty_nonordinary_signature_param_name_span_fallback(ty_id, sig_id, param_id) +} + task v4_ty_signature_param_is_variadic(ty_id: int, sig_id: int, param_id: int) -> bool { give back v4_ty_is_variadic_param_surface(v4_ty_signature_param_surface_type(ty_id, sig_id, param_id)) } @@ -5445,7 +5519,7 @@ task v4_ty_signature_is_ordinary_hir_task(ty_id: int, sig_id: int) -> bool { if hir_id < 0 or hir_item < 0 or hir_item >= v4_hir_item_count(hir_id) { give back false } - give back v4_hir_item_kind(hir_id, hir_item) == v4_hir_task + give back v4_hir_item_is_ordinary_task(hir_id, hir_item) } task v4_ty_ordinary_task_explicit_return_from_hir(hir_id: int, hir_item: int) -> word { diff --git a/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk b/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk new file mode 100644 index 00000000..8fdee2fa --- /dev/null +++ b/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk @@ -0,0 +1,330 @@ +-- V4 ordinary-task parameter HIR ownership smoke fixture. +-- Verification prepends the V4 crates before this file. + +task v4_task_param_bool(value: bool) -> word { + if value { give back "true" } + give back "false" +} + +task v4_task_param_braces(inner: word) -> word { + give back "{" + inner + "}" +} + +task v4_task_param_find_token(stream_id: int, value: word, ordinal: int) -> int { + pilot seen = 0 + pilot token_id = 0 + repeat until token_id >= v4_lex_token_count(stream_id) { + if v4_lex_token_value(stream_id, token_id) == value { + if seen == ordinal { give back token_id } + seen += 1 + } + token_id += 1 + } + give back 0 - 1 +} + +task v4_task_param_offset(stream_id: int, value: word, ordinal: int) -> int { + pilot token_id = v4_task_param_find_token(stream_id, value, ordinal) + if token_id < 0 { give back 0 - 1 } + give back v4_span_start(v4_lex_token_span(stream_id, token_id)) +} + +task v4_task_param_source_text() -> word { + pilot src = "task empty() -> int " + v4_task_param_braces(" give back 0 ") + "\n" + src = src + "task rich<'a>(\n" + src = src + " value: maybe<(word, [int; 2])>,\n" + src = src + " lend 'a borrowed: list>,\n" + src = src + " lend mut 'a changed: [int; 2],\n" + src = src + " matrix: [[int; 2]; 3]\n" + src = src + ") -> int " + v4_task_param_braces(" give back 7 ") + "\n" + src = src + "task named(value: int) -> int " + v4_task_param_braces(" give back value ") + "\n" + src = src + "task caller() -> int " + v4_task_param_braces(" give back named(value: 7) ") + "\n" + give back src +} + +task v4_task_param_snapshot_header(payload: word, original: word, task_param_delta: int) -> word { + pilot out = "hir-snapshot|format=" + v4_hir_snapshot_key_value(original, "format") + out = out + "|files=" + v4_hir_snapshot_key_value(original, "files") + out = out + "|items=" + v4_hir_snapshot_key_value(original, "items") + out = out + "|alias-targets=" + v4_hir_snapshot_key_value(original, "alias-targets") + out = out + "|local-annotations=" + v4_hir_snapshot_key_value(original, "local-annotations") + out = out + "|task-returns=" + v4_hir_snapshot_key_value(original, "task-returns") + out = out + "|task-param-owners=" + v4_hir_snapshot_key_value(original, "task-param-owners") + out = out + "|task-params=" + word_from_int(word_to_int(v4_hir_snapshot_key_value(original, "task-params")) + task_param_delta) + out = out + "|diagnostics=" + v4_hir_snapshot_key_value(original, "diagnostics") + give back out +} + +task v4_task_param_snapshot_variant(payload: word, wanted_hir: int, wanted_item: int, mode: word) -> word { + pilot owner_span = V4_NO_SPAN + pilot line_id = 0 + pilot line_count = v4_hir_snapshot_line_count(payload) + repeat until line_id >= line_count { + pilot line = v4_hir_snapshot_line(payload, line_id) + if v4_hir_snapshot_field_raw(line, 0) == "hir-item" and v4_hir_snapshot_field_raw(line, 1) == word_from_int(wanted_hir) and v4_hir_snapshot_field_raw(line, 2) == word_from_int(wanted_item) { + owner_span = v4_hir_snapshot_field(line, 6) + } + line_id += 1 + } + + pilot out = "" + pilot changed = 0 + line_id = 0 + repeat until line_id >= line_count { + pilot line = v4_hir_snapshot_line(payload, line_id) + pilot kind = v4_hir_snapshot_field_raw(line, 0) + if kind == "hir-snapshot" and mode == "header-count" { + line = v4_task_param_snapshot_header(payload, line, 1) + } else if kind == "hir-item" and mode == "owner-kind" and changed == 0 and v4_hir_snapshot_field_raw(line, 1) == word_from_int(wanted_hir) and v4_hir_snapshot_field_raw(line, 2) == word_from_int(wanted_item) { + pilot rebuilt_item = "hir-item" + pilot item_field = 1 + repeat until item_field >= 10 { + if item_field == 3 { + rebuilt_item = rebuilt_item + "|" + v4_hir_snapshot_escape(v4_hir_shape) + } else { + rebuilt_item = rebuilt_item + "|" + v4_hir_snapshot_field_raw(line, item_field) + } + item_field += 1 + } + line = rebuilt_item + changed = 1 + } else if kind == "hir-task-param-owner" and changed == 0 and v4_hir_snapshot_field_raw(line, 1) == word_from_int(wanted_hir) and v4_hir_snapshot_field_raw(line, 3) == word_from_int(wanted_item) and (mode == "owner" or mode == "count") { + pilot rebuilt_owner = "hir-task-param-owner" + pilot owner_field = 1 + repeat until owner_field >= 5 { + if owner_field == 3 and mode == "owner" { + rebuilt_owner = rebuilt_owner + "|999" + } else if owner_field == 4 and mode == "count" { + rebuilt_owner = rebuilt_owner + "|" + word_from_int(word_to_int(v4_hir_snapshot_field_raw(line, 4)) + 1) + } else { + rebuilt_owner = rebuilt_owner + "|" + v4_hir_snapshot_field_raw(line, owner_field) + } + owner_field += 1 + } + line = rebuilt_owner + changed = 1 + } else if kind == "hir-task-param" and changed == 0 and v4_hir_snapshot_field_raw(line, 1) == word_from_int(wanted_hir) and v4_hir_snapshot_field_raw(line, 3) == word_from_int(wanted_item) and v4_hir_snapshot_field_raw(line, 4) == "1" and mode != "header-count" and mode != "owner-kind" and mode != "owner" and mode != "count" { + pilot rebuilt_param = "hir-task-param" + pilot param_field = 1 + repeat until param_field >= 13 { + if param_field == 2 and mode == "noncanonical" { + rebuilt_param = rebuilt_param + "|0" + v4_hir_snapshot_field_raw(line, param_field) + } else if param_field == 4 and mode == "ordinal" { + rebuilt_param = rebuilt_param + "|0" + } else if param_field == 7 and mode == "mode" { + rebuilt_param = rebuilt_param + "|invented" + } else if param_field == 8 and mode == "lifetime" { + rebuilt_param = rebuilt_param + "|'_" + } else if param_field == 9 and mode == "lifetime-span" { + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape(V4_NO_SPAN) + } else if param_field == 12 and mode == "span" { + pilot forged_start = v4_span_end(owner_span) + 1 + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape(v4_span_new(v4_span_file(owner_span), forged_start, forged_start + 5)) + } else { + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_field_raw(line, param_field) + } + param_field += 1 + } + line = rebuilt_param + changed = 1 + } + if line_id > 0 { out = out + "\n" } + out = out + line + line_id += 1 + } + give back out +} + +task v4_task_param_invalidation_positive(report: word, key: word) -> bool { + give back word_to_int(v4_unit_snapshot_key_value(report, key)) > 0 +} + +task v4_task_param_invalidation_probe() -> void { + pilot path = "task-param-invalidation.fk" + pilot before = "task changed(value: int) -> int " + v4_task_param_braces(" give back 7 ") + "\n" + pilot after = "task changed(value: num) -> int " + v4_task_param_braces(" give back 7 ") + "\n" + pilot before_stream = v4_lex_text(40, before) + pilot before_use = v4_task_param_offset(before_stream, "value", 0) + v4_lsp_open_document(path, before) + + pilot before_hir = v4_hir_text_cached(path, before) + pilot before_ty = v4_ty_text_cached(path, before) + pilot before_mir = v4_mir_text_cached(path, before) + pilot before_borrow = v4_borrowck_text_cached(path, before) + pilot before_hover = v4_hover_text_cached(path, before, before_use) + pilot before_resolve = v4_ty_resolve_id(before_ty) + pilot before_def = v4_resolve_def_for_name(before_resolve, "changed") + pilot before_sig = v4_ty_lookup_signature(before_ty, before_def) + pilot before_item = v4_ty_signature_hir_item(before_ty, before_sig) + pilot before_body = v4_mir_lookup_body(before_mir, before_def) + pilot before_local = v4_mir_find_local(before_mir, before_body, "value") + pilot before_borrow_state = v4_borrowck_lookup_result(before_borrow, before_def) + say "task-param-invalidation-before-hir=" + v4_hir_task_param_surface_type(before_hir, before_item, 0) + say "task-param-invalidation-before-ty=" + v4_ty_signature_param_type(before_ty, before_sig, 0) + say "task-param-invalidation-before-mir=" + v4_mir_local_ty(before_mir, before_body, before_local) + say "task-param-invalidation-before-borrow=" + v4_borrowck_result_status(before_borrow, before_borrow_state) + say "task-param-invalidation-before-editor=" + v4_hover_type(before_hover) + + pilot change = v4_lsp_handle_text_request("textDocument/didChange", path, after, 0) + pilot report = v4_unit_snapshot_line(change, 2) + say "task-param-invalidation-hir=" + v4_task_param_bool(v4_task_param_invalidation_positive(report, "hir-invalidations-added")) + say "task-param-invalidation-ty=" + v4_task_param_bool(v4_task_param_invalidation_positive(report, "ty-invalidations-added")) + say "task-param-invalidation-mir=" + v4_task_param_bool(v4_task_param_invalidation_positive(report, "mir-invalidations-added")) + say "task-param-invalidation-borrowck=" + v4_task_param_bool(v4_task_param_invalidation_positive(report, "borrowck-invalidations-added")) + say "task-param-invalidation-editor=" + v4_task_param_bool(v4_task_param_invalidation_positive(report, "editor-invalidations-added")) + + pilot after_hir = v4_hir_text_cached(path, after) + pilot after_ty = v4_ty_text_cached(path, after) + pilot after_mir = v4_mir_text_cached(path, after) + pilot after_borrow = v4_borrowck_text_cached(path, after) + pilot after_hover = v4_hover_text_cached(path, after, before_use) + pilot after_resolve = v4_ty_resolve_id(after_ty) + pilot after_def = v4_resolve_def_for_name(after_resolve, "changed") + pilot after_sig = v4_ty_lookup_signature(after_ty, after_def) + pilot after_item = v4_ty_signature_hir_item(after_ty, after_sig) + pilot after_body = v4_mir_lookup_body(after_mir, after_def) + pilot after_local = v4_mir_find_local(after_mir, after_body, "value") + pilot after_borrow_state = v4_borrowck_lookup_result(after_borrow, after_def) + say "task-param-invalidation-after-hir=" + v4_hir_task_param_surface_type(after_hir, after_item, 0) + say "task-param-invalidation-after-ty=" + v4_ty_signature_param_type(after_ty, after_sig, 0) + say "task-param-invalidation-after-mir=" + v4_mir_local_ty(after_mir, after_body, after_local) + say "task-param-invalidation-after-borrow=" + v4_borrowck_result_status(after_borrow, after_borrow_state) + say "task-param-invalidation-after-editor=" + v4_hover_type(after_hover) +} + +task v4_task_param_invalid_source_probe() -> void { + pilot src = "task broken(lend mut : int, kept: word) -> int " + v4_task_param_braces(" give back 0 ") + "\n" + pilot stream_id = v4_lex_text(41, src) + pilot tree_id = v4_parse_stream(41, stream_id) + pilot hir_id = v4_hir_lower_tree(41, tree_id) + pilot task_item = 0 - 1 + pilot item_id = 0 + repeat until item_id >= v4_hir_item_count(hir_id) { + if v4_hir_item_name(hir_id, item_id) == "broken" { + task_item = item_id + } + item_id += 1 + } + pilot no_invented = true + if task_item >= 0 { + no_invented = v4_hir_task_param_count(hir_id, task_item) <= 1 + } + say "task-param-invalid-hir-diagnostics=" + word_from_int(v4_hir_diag_count(hir_id)) + say "task-param-invalid-no-invented=" + v4_task_param_bool(no_invented) +} + +pilot v4_task_param_source = v4_task_param_source_text() +pilot v4_task_param_stream = v4_lex_text(0, v4_task_param_source) +pilot v4_task_param_tree = v4_parse_stream(0, v4_task_param_stream) +pilot v4_task_param_hir = v4_hir_lower_tree(0, v4_task_param_tree) +pilot v4_task_param_resolve = v4_resolve_lower_hir(0, v4_task_param_hir) +pilot v4_task_param_ty = v4_ty_lower_resolve(0, v4_task_param_resolve) +pilot v4_task_param_mir = v4_mir_lower_ty(0, v4_task_param_ty) +pilot v4_task_param_borrow = v4_borrowck_check_mir(0, v4_task_param_mir) + +pilot v4_task_param_empty_def = v4_resolve_def_for_name(v4_task_param_resolve, "empty") +pilot v4_task_param_rich_def = v4_resolve_def_for_name(v4_task_param_resolve, "rich") +pilot v4_task_param_rich_sig = v4_ty_lookup_signature(v4_task_param_ty, v4_task_param_rich_def) +pilot v4_task_param_empty_sig = v4_ty_lookup_signature(v4_task_param_ty, v4_task_param_empty_def) +pilot v4_task_param_rich_item = v4_ty_signature_hir_item(v4_task_param_ty, v4_task_param_rich_sig) +pilot v4_task_param_empty_item = v4_ty_signature_hir_item(v4_task_param_ty, v4_task_param_empty_sig) +pilot v4_task_param_rich_body = v4_mir_lookup_body(v4_task_param_mir, v4_task_param_rich_def) +pilot v4_task_param_rich_borrow = v4_borrowck_lookup_result(v4_task_param_borrow, v4_task_param_rich_def) +pilot v4_task_param_value_local = v4_mir_find_local(v4_task_param_mir, v4_task_param_rich_body, "value") +pilot v4_task_param_borrowed_local = v4_mir_find_local(v4_task_param_mir, v4_task_param_rich_body, "borrowed") +pilot v4_task_param_changed_local = v4_mir_find_local(v4_task_param_mir, v4_task_param_rich_body, "changed") + +pilot v4_task_param_value_name_span = v4_ty_signature_param_name_span(v4_task_param_ty, v4_task_param_rich_sig, 0) +pilot v4_task_param_value_type_span = v4_ty_signature_param_type_span(v4_task_param_ty, v4_task_param_rich_sig, 0) +pilot v4_task_param_value_segment_span = v4_ty_signature_param_segment_span(v4_task_param_ty, v4_task_param_rich_sig, 0) +pilot v4_task_param_borrowed_lifetime_span = v4_ty_signature_param_lifetime_span(v4_task_param_ty, v4_task_param_rich_sig, 1) +pilot v4_task_param_hir_borrowed_name_span = v4_hir_task_param_name_span(v4_task_param_hir, v4_task_param_rich_item, 1) +pilot v4_task_param_hir_borrowed_type_span = v4_hir_task_param_type_span(v4_task_param_hir, v4_task_param_rich_item, 1) +pilot v4_task_param_hir_borrowed_segment_span = v4_hir_task_param_segment_span(v4_task_param_hir, v4_task_param_rich_item, 1) + +say "task-param-parse-diagnostics=" + word_from_int(v4_parse_diag_count(v4_task_param_tree)) +say "task-param-hir-diagnostics=" + word_from_int(v4_hir_diag_count(v4_task_param_hir)) +say "task-param-empty-count=" + word_from_int(v4_hir_task_param_count(v4_task_param_hir, v4_task_param_empty_item)) +say "task-param-rich-hir-count=" + word_from_int(v4_hir_task_param_count(v4_task_param_hir, v4_task_param_rich_item)) +say "task-param-hir-borrowed-name=" + v4_hir_task_param_name(v4_task_param_hir, v4_task_param_rich_item, 1) +say "task-param-hir-borrowed-name-source=" + v4_slice(v4_task_param_source, v4_span_start(v4_task_param_hir_borrowed_name_span), v4_span_end(v4_task_param_hir_borrowed_name_span)) +say "task-param-hir-borrowed-mode=" + v4_hir_task_param_mode(v4_task_param_hir, v4_task_param_rich_item, 1) +say "task-param-hir-borrowed-lifetime=" + v4_hir_task_param_lifetime(v4_task_param_hir, v4_task_param_rich_item, 1) +say "task-param-hir-borrowed-surface=" + v4_hir_task_param_surface_type(v4_task_param_hir, v4_task_param_rich_item, 1) +say "task-param-hir-borrowed-type-source=" + v4_slice(v4_task_param_source, v4_span_start(v4_task_param_hir_borrowed_type_span), v4_span_end(v4_task_param_hir_borrowed_type_span)) +say "task-param-hir-borrowed-segment-source=" + v4_slice(v4_task_param_source, v4_span_start(v4_task_param_hir_borrowed_segment_span), v4_span_end(v4_task_param_hir_borrowed_segment_span)) +say "task-param-rich-ty-count=" + word_from_int(v4_ty_signature_param_count(v4_task_param_ty, v4_task_param_rich_sig)) +say "task-param-value-name=" + v4_ty_signature_param_name(v4_task_param_ty, v4_task_param_rich_sig, 0) +say "task-param-value-name-source=" + v4_slice(v4_task_param_source, v4_span_start(v4_task_param_value_name_span), v4_span_end(v4_task_param_value_name_span)) +say "task-param-value-surface=" + v4_ty_signature_param_surface_type(v4_task_param_ty, v4_task_param_rich_sig, 0) +say "task-param-value-canonical=" + v4_ty_signature_param_type(v4_task_param_ty, v4_task_param_rich_sig, 0) +say "task-param-value-type-source=" + v4_slice(v4_task_param_source, v4_span_start(v4_task_param_value_type_span), v4_span_end(v4_task_param_value_type_span)) +say "task-param-value-segment-source=" + v4_slice(v4_task_param_source, v4_span_start(v4_task_param_value_segment_span), v4_span_end(v4_task_param_value_segment_span)) +say "task-param-value-mode=" + v4_ty_signature_param_mode(v4_task_param_ty, v4_task_param_rich_sig, 0) +say "task-param-borrowed-mode=" + v4_ty_signature_param_mode(v4_task_param_ty, v4_task_param_rich_sig, 1) +say "task-param-borrowed-lifetime=" + v4_ty_signature_param_lifetime(v4_task_param_ty, v4_task_param_rich_sig, 1) +say "task-param-borrowed-lifetime-source=" + v4_slice(v4_task_param_source, v4_span_start(v4_task_param_borrowed_lifetime_span), v4_span_end(v4_task_param_borrowed_lifetime_span)) +say "task-param-borrowed-surface=" + v4_ty_signature_param_surface_type(v4_task_param_ty, v4_task_param_rich_sig, 1) +say "task-param-changed-mode=" + v4_ty_signature_param_mode(v4_task_param_ty, v4_task_param_rich_sig, 2) +say "task-param-changed-surface=" + v4_ty_signature_param_surface_type(v4_task_param_ty, v4_task_param_rich_sig, 2) +say "task-param-matrix-surface=" + v4_ty_signature_param_surface_type(v4_task_param_ty, v4_task_param_rich_sig, 3) +say "task-param-mir-value-name=" + v4_mir_local_name(v4_task_param_mir, v4_task_param_rich_body, v4_task_param_value_local) +say "task-param-mir-value-type=" + v4_mir_local_ty(v4_task_param_mir, v4_task_param_rich_body, v4_task_param_value_local) +say "task-param-mir-borrowed-mode=" + v4_mir_local_mode(v4_task_param_mir, v4_task_param_rich_body, v4_task_param_borrowed_local) +say "task-param-mir-changed-mode=" + v4_mir_local_mode(v4_task_param_mir, v4_task_param_rich_body, v4_task_param_changed_local) +say "task-param-mir-span-semantic=" + v4_task_param_bool(v4_mir_local_span(v4_task_param_mir, v4_task_param_rich_body, v4_task_param_borrowed_local) == v4_ty_signature_param_segment_span(v4_task_param_ty, v4_task_param_rich_sig, 1)) +say "task-param-meiya-status=" + v4_borrowck_result_status(v4_task_param_borrow, v4_task_param_rich_borrow) + +pilot v4_task_param_named_decl = v4_task_param_offset(v4_task_param_stream, "value", 1) +pilot v4_task_param_named_use = v4_task_param_offset(v4_task_param_stream, "value", 2) +pilot v4_task_param_named_label = v4_task_param_offset(v4_task_param_stream, "value", 3) +pilot v4_task_param_hover = v4_hover_text_cached("task-param-boundary.fk", v4_task_param_source, v4_task_param_named_use) +pilot v4_task_param_definition = v4_definition_at_text_cached("task-param-boundary.fk", v4_task_param_source, v4_task_param_named_use) +pilot v4_task_param_label_semantic = v4_semantic_at_text_cached("task-param-boundary.fk", v4_task_param_source, v4_task_param_named_label) +pilot v4_task_param_label_definition = v4_definition_at_text_cached("task-param-boundary.fk", v4_task_param_source, v4_task_param_named_label) +say "task-param-editor-hover=" + v4_hover_type(v4_task_param_hover) +say "task-param-editor-definition=" + v4_task_param_bool(v4_definition_at_found(v4_task_param_definition) == 1 and v4_span_start(v4_definition_at_span(v4_task_param_definition)) == v4_task_param_named_decl) +say "task-param-editor-label-kind=" + v4_semantic_at_kind(v4_task_param_label_semantic) +say "task-param-editor-label-type=" + v4_semantic_at_type(v4_task_param_label_semantic) +say "task-param-editor-label-definition=" + v4_task_param_bool(v4_definition_at_found(v4_task_param_label_definition) == 1 and v4_span_start(v4_definition_at_span(v4_task_param_label_definition)) == v4_task_param_named_decl) + +pilot v4_task_param_snapshot = v4_hir_snapshot() +say v4_hir_snapshot_summary() +say v4_hir_snapshot_restore(v4_task_param_snapshot) +say "task-param-restored-count=" + word_from_int(v4_hir_task_param_count(v4_task_param_hir, v4_task_param_rich_item)) +say "task-param-restored-type=" + v4_hir_task_param_surface_type(v4_task_param_hir, v4_task_param_rich_item, 0) + +pilot v4_task_param_before_bad_files = v4_hir_file_count() +pilot v4_task_param_before_bad_count = v4_hir_task_param_count(v4_task_param_hir, v4_task_param_rich_item) +pilot v4_task_param_schema_rejected = true +pilot v4_task_param_schema_atomic = true +pilot v4_task_param_modes = array_new() +array_push(v4_task_param_modes, "owner") +array_push(v4_task_param_modes, "count") +array_push(v4_task_param_modes, "ordinal") +array_push(v4_task_param_modes, "mode") +array_push(v4_task_param_modes, "lifetime") +array_push(v4_task_param_modes, "lifetime-span") +array_push(v4_task_param_modes, "span") +array_push(v4_task_param_modes, "noncanonical") +array_push(v4_task_param_modes, "owner-kind") +array_push(v4_task_param_modes, "header-count") +pilot v4_task_param_mode_id = 0 +repeat until v4_task_param_mode_id >= array_len(v4_task_param_modes) { + pilot v4_task_param_schema_mode: word = array_get(v4_task_param_modes, v4_task_param_mode_id) + pilot v4_task_param_variant = v4_task_param_snapshot_variant(v4_task_param_snapshot, v4_task_param_hir, v4_task_param_rich_item, v4_task_param_schema_mode) + pilot v4_task_param_validation = v4_hir_snapshot_validate(v4_task_param_variant) + pilot v4_task_param_restore = v4_hir_snapshot_restore(v4_task_param_variant) + if v4_task_param_validation.starts_with("hir-snapshot-import ok=0") == false or v4_task_param_restore.starts_with("hir-snapshot-restore ok=0 reason=validation-failed") == false { + v4_task_param_schema_rejected = false + } + if v4_hir_file_count() != v4_task_param_before_bad_files or v4_hir_task_param_count(v4_task_param_hir, v4_task_param_rich_item) != v4_task_param_before_bad_count or v4_hir_task_param_surface_type(v4_task_param_hir, v4_task_param_rich_item, 0) != "maybe<(word,[int;2])>" { + v4_task_param_schema_atomic = false + } + v4_task_param_mode_id += 1 +} +say "task-param-schema-variants-rejected=" + v4_task_param_bool(v4_task_param_schema_rejected) +say "task-param-schema-variants-atomic=" + v4_task_param_bool(v4_task_param_schema_atomic) + +v4_task_param_invalid_source_probe() +v4_task_param_invalidation_probe() From cd5b6143db57a8c0bcfb85467439ebfe6e14e107 Mon Sep 17 00:00:00 2001 From: TeRiRi_606 <147689545+OttoApocalypse69@users.noreply.github.com> Date: Thu, 13 Aug 2026 20:35:43 +0300 Subject: [PATCH 2/5] Harden task parameter snapshot restore - Reject over-wide parameter records and impossible identifier facts - Enforce semantic span order before restoring editor and TY inputs - Extend adversarial and nonordinary boundary coverage --- src/compiler/v4/crates/freak_hir/src/lib.fk | 32 +++++++- .../task_param_semantic_boundary_smoke.fk | 77 ++++++++++++++++++- 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/src/compiler/v4/crates/freak_hir/src/lib.fk b/src/compiler/v4/crates/freak_hir/src/lib.fk index e2a5c38f..52fea219 100644 --- a/src/compiler/v4/crates/freak_hir/src/lib.fk +++ b/src/compiler/v4/crates/freak_hir/src/lib.fk @@ -2027,6 +2027,22 @@ task v4_hir_snapshot_named_lifetime_is_valid(lifetime_name: word) -> bool { give back true } +task v4_hir_snapshot_task_param_name_is_valid(name: word) -> bool { + if name == "" or v4_lex_is_ident_start(name.char_at(0)) == false { + give back false + } + pilot idx = 1 + repeat until idx >= name.length() { + if v4_lex_is_ident_continue(name.char_at(idx)) == false { + give back false + } + idx += 1 + } + -- Lowering only accepts v4_tok_ident. Keywords and the case-insensitive + -- boolean vocabulary are emitted as distinct token kinds by freak_lex. + give back v4_lex_is_keyword_word(name) == false and v4_lex_is_bool_word(name) == false +} + task v4_hir_snapshot_task_param_is_valid(line: word) -> bool { if v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 1)) == false or v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 2)) == false or v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 3)) == false or v4_hir_snapshot_nonnegative_int_is_valid(v4_hir_snapshot_field_raw(line, 4)) == false { give back false @@ -2040,7 +2056,7 @@ task v4_hir_snapshot_task_param_is_valid(line: word) -> bool { pilot type_span = v4_hir_snapshot_field(line, 11) pilot segment_span = v4_hir_snapshot_field(line, 12) pilot no_span = V4_NO_SPAN - if name == "" or type_text == "" { + if v4_hir_snapshot_task_param_name_is_valid(name) == false or type_text == "" { give back false } if mode != v4_hir_task_param_mode_value and mode != v4_hir_task_param_mode_lend and mode != v4_hir_task_param_mode_lend_mut { @@ -2064,6 +2080,15 @@ task v4_hir_snapshot_task_param_is_valid(line: word) -> bool { if v4_hir_snapshot_span_is_contained(name_span, segment_span) == false or v4_hir_snapshot_span_is_contained(type_span, segment_span) == false { give back false } + -- These facts feed editor definitions and TY diagnostics after restore. + -- Preserve the source order guaranteed by lowering instead of accepting + -- overlapping or retargeted semantic spans that merely share an owner. + if v4_span_end(name_span) >= v4_span_start(type_span) { + give back false + } + if lifetime_name != "" and v4_span_end(lifetime_span) >= v4_span_start(name_span) { + give back false + } give back true } @@ -2558,6 +2583,11 @@ task v4_hir_snapshot_record_is_valid(line: word) -> bool { if v4_hir_snapshot_field_count(line) < expected { give back false } + -- Parameter records are new in v6 and have a closed canonical schema. + -- Reject extensions rather than silently restoring only the known prefix. + if (kind == "hir-task-param-owner" or kind == "hir-task-param") and v4_hir_snapshot_field_count(line) != expected { + give back false + } if kind == "hir-item" and v4_hir_snapshot_alias_target_is_valid(line) == false { give back false } diff --git a/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk b/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk index 8fdee2fa..f1766ce1 100644 --- a/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk +++ b/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk @@ -88,7 +88,7 @@ task v4_task_param_snapshot_variant(payload: word, wanted_hir: int, wanted_item: } line = rebuilt_item changed = 1 - } else if kind == "hir-task-param-owner" and changed == 0 and v4_hir_snapshot_field_raw(line, 1) == word_from_int(wanted_hir) and v4_hir_snapshot_field_raw(line, 3) == word_from_int(wanted_item) and (mode == "owner" or mode == "count") { + } else if kind == "hir-task-param-owner" and changed == 0 and v4_hir_snapshot_field_raw(line, 1) == word_from_int(wanted_hir) and v4_hir_snapshot_field_raw(line, 3) == word_from_int(wanted_item) and (mode == "owner" or mode == "count" or mode == "owner-over-wide") { pilot rebuilt_owner = "hir-task-param-owner" pilot owner_field = 1 repeat until owner_field >= 5 { @@ -101,6 +101,9 @@ task v4_task_param_snapshot_variant(payload: word, wanted_hir: int, wanted_item: } owner_field += 1 } + if mode == "owner-over-wide" { + rebuilt_owner = rebuilt_owner + "|unexpected" + } line = rebuilt_owner changed = 1 } else if kind == "hir-task-param" and changed == 0 and v4_hir_snapshot_field_raw(line, 1) == word_from_int(wanted_hir) and v4_hir_snapshot_field_raw(line, 3) == word_from_int(wanted_item) and v4_hir_snapshot_field_raw(line, 4) == "1" and mode != "header-count" and mode != "owner-kind" and mode != "owner" and mode != "count" { @@ -111,12 +114,22 @@ task v4_task_param_snapshot_variant(payload: word, wanted_hir: int, wanted_item: rebuilt_param = rebuilt_param + "|0" + v4_hir_snapshot_field_raw(line, param_field) } else if param_field == 4 and mode == "ordinal" { rebuilt_param = rebuilt_param + "|0" + } else if param_field == 5 and mode == "name-spacing" { + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape("bad name") + } else if param_field == 5 and mode == "name-punctuation" { + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape("bad-name") + } else if param_field == 5 and mode == "name-keyword" { + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape("task") + } else if param_field == 6 and mode == "name-span-reordered" { + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_field_raw(line, 11) } else if param_field == 7 and mode == "mode" { rebuilt_param = rebuilt_param + "|invented" } else if param_field == 8 and mode == "lifetime" { rebuilt_param = rebuilt_param + "|'_" } else if param_field == 9 and mode == "lifetime-span" { rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape(V4_NO_SPAN) + } else if param_field == 9 and mode == "lifetime-span-overlap" { + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_field_raw(line, 6) } else if param_field == 12 and mode == "span" { pilot forged_start = v4_span_end(owner_span) + 1 rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape(v4_span_new(v4_span_file(owner_span), forged_start, forged_start + 5)) @@ -125,6 +138,9 @@ task v4_task_param_snapshot_variant(payload: word, wanted_hir: int, wanted_item: } param_field += 1 } + if mode == "param-over-wide" { + rebuilt_param = rebuilt_param + "|unexpected" + } line = rebuilt_param changed = 1 } @@ -213,6 +229,56 @@ task v4_task_param_invalid_source_probe() -> void { say "task-param-invalid-no-invented=" + v4_task_param_bool(no_invented) } +task v4_task_param_find_hir_item(hir_id: int, kind: word, name: word) -> int { + pilot item_id = 0 + repeat until item_id >= v4_hir_item_count(hir_id) { + if v4_hir_item_kind(hir_id, item_id) == kind and (name == "" or v4_hir_item_name(hir_id, item_id) == name) { + give back item_id + } + item_id += 1 + } + give back 0 - 1 +} + +task v4_task_param_residual_hir_probe() -> void { + pilot src = "task anonymous(lend '_ borrowed: word) -> int " + v4_task_param_braces(" give back 0 ") + "\n" + src = src + "task immortal(lend 'static borrowed: word) -> int " + v4_task_param_braces(" give back 0 ") + "\n" + src = src + "task curly(value: Box<" + v4_task_param_braces("left:int,right:int") + ",word>) -> int " + v4_task_param_braces(" give back 0 ") + "\n" + pilot stream_id = v4_lex_text(42, src) + pilot tree_id = v4_parse_stream(42, stream_id) + pilot hir_id = v4_hir_lower_tree(42, tree_id) + pilot anonymous_item = v4_task_param_find_hir_item(hir_id, v4_hir_task, "anonymous") + pilot immortal_item = v4_task_param_find_hir_item(hir_id, v4_hir_task, "immortal") + pilot curly_item = v4_task_param_find_hir_item(hir_id, v4_hir_task, "curly") + pilot curly_type = "Box<" + v4_task_param_braces("left:int,right:int") + ",word>" + say "task-param-anonymous-normalized=" + v4_task_param_bool(v4_hir_task_param_lifetime(hir_id, anonymous_item, 0) == "" and v4_hir_task_param_lifetime_span(hir_id, anonymous_item, 0) == V4_NO_SPAN) + say "task-param-static-preserved=" + v4_task_param_bool(v4_hir_task_param_lifetime(hir_id, immortal_item, 0) == "'static" and v4_hir_task_param_lifetime_span(hir_id, immortal_item, 0) != V4_NO_SPAN) + say "task-param-curly-nesting=" + v4_task_param_bool(v4_hir_task_param_count(hir_id, curly_item) == 1 and v4_hir_task_param_surface_type(hir_id, curly_item, 0) == curly_type) +} + +task v4_task_param_nonordinary_probe() -> void { + pilot doctrine_body = "\n task echo(self, value: word) -> word\n" + pilot shape_body = "\n value: word\n" + pilot impl_body = "\n task echo(self, value: word) -> word " + v4_task_param_braces(" give back value ") + "\n" + pilot extern_body = "\n task native(input: *const tiny) -> std::ffi::c_int\n" + pilot src = "doctrine Echo " + v4_task_param_braces(doctrine_body) + "\n" + src = src + "shape Packet " + v4_task_param_braces(shape_body) + "\n" + src = src + "impl Echo for Packet " + v4_task_param_braces(impl_body) + "\n" + src = src + "extern [C] " + v4_task_param_braces(extern_body) + "\n" + pilot stream_id = v4_lex_text(43, src) + pilot tree_id = v4_parse_stream(43, stream_id) + pilot hir_id = v4_hir_lower_tree(43, tree_id) + pilot resolve_id = v4_resolve_lower_hir(43, hir_id) + pilot ty_id = v4_ty_lower_resolve(43, resolve_id) + pilot doctrine_sig = v4_ty_doctrine_signature_id_for_name(ty_id, "Echo") + pilot impl_item = v4_task_param_find_hir_item(hir_id, v4_hir_impl, "") + pilot extern_sig = v4_ty_task_signature_id_for_name(ty_id, "native") + say "task-param-nonordinary-owner-records=" + word_from_int(v4_hir_task_param_owner_record_count(hir_id)) + say "task-param-doctrine-fallback=" + v4_task_param_bool(v4_ty_doctrine_method_explicit_param_count(ty_id, doctrine_sig, 0) == 1 and v4_ty_doctrine_method_explicit_param_name(ty_id, doctrine_sig, 0, 0) == "value" and v4_ty_doctrine_method_explicit_param_surface_type(ty_id, doctrine_sig, 0, 0) == "word") + say "task-param-impl-fallback=" + v4_task_param_bool(v4_ty_impl_method_explicit_param_count(ty_id, impl_item, 0) == 1 and v4_ty_impl_method_explicit_param_name(ty_id, impl_item, 0, 0) == "value" and v4_ty_impl_method_explicit_param_type(ty_id, impl_item, 0, 0) == "word") + say "task-param-extern-fallback=" + v4_task_param_bool(v4_ty_signature_is_ordinary_hir_task(ty_id, extern_sig) == false and v4_ty_signature_param_count(ty_id, extern_sig) == 1 and v4_ty_signature_param_name(ty_id, extern_sig, 0) == "input" and v4_ty_signature_param_surface_type(ty_id, extern_sig, 0) == "*consttiny") +} + pilot v4_task_param_source = v4_task_param_source_text() pilot v4_task_param_stream = v4_lex_text(0, v4_task_param_source) pilot v4_task_param_tree = v4_parse_stream(0, v4_task_param_stream) @@ -301,10 +367,17 @@ pilot v4_task_param_schema_atomic = true pilot v4_task_param_modes = array_new() array_push(v4_task_param_modes, "owner") array_push(v4_task_param_modes, "count") +array_push(v4_task_param_modes, "owner-over-wide") +array_push(v4_task_param_modes, "param-over-wide") array_push(v4_task_param_modes, "ordinal") +array_push(v4_task_param_modes, "name-spacing") +array_push(v4_task_param_modes, "name-punctuation") +array_push(v4_task_param_modes, "name-keyword") +array_push(v4_task_param_modes, "name-span-reordered") array_push(v4_task_param_modes, "mode") array_push(v4_task_param_modes, "lifetime") array_push(v4_task_param_modes, "lifetime-span") +array_push(v4_task_param_modes, "lifetime-span-overlap") array_push(v4_task_param_modes, "span") array_push(v4_task_param_modes, "noncanonical") array_push(v4_task_param_modes, "owner-kind") @@ -327,4 +400,6 @@ say "task-param-schema-variants-rejected=" + v4_task_param_bool(v4_task_param_sc say "task-param-schema-variants-atomic=" + v4_task_param_bool(v4_task_param_schema_atomic) v4_task_param_invalid_source_probe() +v4_task_param_residual_hir_probe() +v4_task_param_nonordinary_probe() v4_task_param_invalidation_probe() From f7963e676fcc3fab77d1671c44b7354fc57ccb6b Mon Sep 17 00:00:00 2001 From: TeRiRi_606 <147689545+OttoApocalypse69@users.noreply.github.com> Date: Thu, 13 Aug 2026 20:46:36 +0300 Subject: [PATCH 3/5] Test boolean parameter name snapshot rejection - Mutate a valid v6 parameter name to case-insensitive TRUE vocabulary\n- Require rejected restores to preserve the byte-identical HIR snapshot --- .../v4/tests/task_param_semantic_boundary_smoke.fk | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk b/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk index f1766ce1..877b9103 100644 --- a/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk +++ b/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk @@ -1,6 +1,10 @@ -- V4 ordinary-task parameter HIR ownership smoke fixture. -- Verification prepends the V4 crates before this file. +-- Snapshot mutation marker: TRUE is canonical case-insensitive boolean +-- vocabulary and therefore cannot be restored as an identifier-owned name. +pilot v4_task_param_bool_name_mutation_marker = "TRUE" + task v4_task_param_bool(value: bool) -> word { if value { give back "true" } give back "false" @@ -120,6 +124,8 @@ task v4_task_param_snapshot_variant(payload: word, wanted_hir: int, wanted_item: rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape("bad-name") } else if param_field == 5 and mode == "name-keyword" { rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape("task") + } else if param_field == 5 and mode == "name-bool-vocabulary" { + rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_escape(v4_task_param_bool_name_mutation_marker) } else if param_field == 6 and mode == "name-span-reordered" { rebuilt_param = rebuilt_param + "|" + v4_hir_snapshot_field_raw(line, 11) } else if param_field == 7 and mode == "mode" { @@ -362,6 +368,7 @@ say "task-param-restored-type=" + v4_hir_task_param_surface_type(v4_task_param_h pilot v4_task_param_before_bad_files = v4_hir_file_count() pilot v4_task_param_before_bad_count = v4_hir_task_param_count(v4_task_param_hir, v4_task_param_rich_item) +pilot v4_task_param_before_bad_snapshot = v4_hir_snapshot() pilot v4_task_param_schema_rejected = true pilot v4_task_param_schema_atomic = true pilot v4_task_param_modes = array_new() @@ -373,6 +380,7 @@ array_push(v4_task_param_modes, "ordinal") array_push(v4_task_param_modes, "name-spacing") array_push(v4_task_param_modes, "name-punctuation") array_push(v4_task_param_modes, "name-keyword") +array_push(v4_task_param_modes, "name-bool-vocabulary") array_push(v4_task_param_modes, "name-span-reordered") array_push(v4_task_param_modes, "mode") array_push(v4_task_param_modes, "lifetime") @@ -391,7 +399,7 @@ repeat until v4_task_param_mode_id >= array_len(v4_task_param_modes) { if v4_task_param_validation.starts_with("hir-snapshot-import ok=0") == false or v4_task_param_restore.starts_with("hir-snapshot-restore ok=0 reason=validation-failed") == false { v4_task_param_schema_rejected = false } - if v4_hir_file_count() != v4_task_param_before_bad_files or v4_hir_task_param_count(v4_task_param_hir, v4_task_param_rich_item) != v4_task_param_before_bad_count or v4_hir_task_param_surface_type(v4_task_param_hir, v4_task_param_rich_item, 0) != "maybe<(word,[int;2])>" { + if v4_hir_file_count() != v4_task_param_before_bad_files or v4_hir_task_param_count(v4_task_param_hir, v4_task_param_rich_item) != v4_task_param_before_bad_count or v4_hir_task_param_surface_type(v4_task_param_hir, v4_task_param_rich_item, 0) != "maybe<(word,[int;2])>" or v4_hir_snapshot() != v4_task_param_before_bad_snapshot { v4_task_param_schema_atomic = false } v4_task_param_mode_id += 1 From e2fe81fde0362b11a6a168694ffd3c697c0a5485 Mon Sep 17 00:00:00 2001 From: TeRiRi_606 <147689545+OttoApocalypse69@users.noreply.github.com> Date: Thu, 13 Aug 2026 21:11:59 +0300 Subject: [PATCH 4/5] Complete ordinary task parameter HIR boundary - Register HIR v6 parameter snapshot and invalidation coverage - Guard ordinary TY adapters against syntax reconstruction - Preserve semantic parameter scopes through MIR and editor consumers --- freak-conformance-audit.md | 4 +- freakc/auditor.py | 95 ++++++- src/compiler/v4/README.md | 17 +- src/compiler/v4/check_v4.py | 235 +++++++++++++++++- src/compiler/v4/crates/freak_hir/src/lib.fk | 8 +- .../v4/crates/freak_mir_build/src/lib.fk | 12 +- .../task_param_semantic_boundary_smoke.fk | 16 +- .../task_return_semantic_boundary_smoke.fk | 5 + 8 files changed, 357 insertions(+), 35 deletions(-) diff --git a/freak-conformance-audit.md b/freak-conformance-audit.md index 7a438d2e..4b950959 100644 --- a/freak-conformance-audit.md +++ b/freak-conformance-audit.md @@ -96,14 +96,14 @@ Verdict legend: 🛠 code fix, 📖 amend bible, ✅ already aligned. |---|---|---|---| | `pilot x = value` declares variable, mutable by default | ✅ | ✅ | [freakc/parser.py:900-950](freakc/parser.py); confirmed by `tests/suite/test_variables.fk` | | `fixed pilot x = value` immutable | ✅ | ✅ | parsed and enforced | -| Type annotation optional / inferred | ✅ | ✅ | The shipping checker infers unannotated literals. In V4, task-local `pilot` and `fixed pilot` annotations—including tuple and fixed-array annotations used by tuple/list destructuring—are normalized with exact spans into HIR snapshot v5 facts, exposed/canonicalized by TY, and consumed by MIR build without re-reading their type tokens. MIR build still uses body tokens for patterns, initializer boundaries, places, and CFG; six unrelated type-text callers remain guarded, backend representation is unchanged, and symbol-valued annotated locals retain the existing phantom-local-IR limitation. | +| Type annotation optional / inferred | ✅ | ✅ | The shipping checker infers unannotated literals. In V4, task-local `pilot` and `fixed pilot` annotations—including tuple and fixed-array annotations used by tuple/list destructuring—are normalized with exact spans into HIR snapshot v6 facts, exposed/canonicalized by TY, and consumed by MIR build without re-reading their type tokens. MIR build still uses body tokens for patterns, initializer boundaries, places, and CFG; six unrelated type-text callers remain guarded, backend representation is unchanged, and symbol-valued annotated locals retain the existing phantom-local-IR limitation. | | `pilot mut x = ...` (Phase-1 BC) for explicit mutability under `--strict-borrow` | ✅ | 📖 | [src/compiler/v3/checker.fk](src/compiler/v3/checker.fk) — bible should mention this dual mode (default leak-everything vs `--strict-borrow`) | #### §1.2 Functions ([freak-full-bible.md:42-71](freak-full-bible.md)) | Contract | Status | Verdict | Notes | |---|---|---|---| -| `task name(...) -> type { ... }` | ✅ | ✅ | Core feature. V4 stores ordinary top-level tasks as closed `explicit` / `implicit-block` / `arrow` HIR return-form facts; an explicit `-> T` carries normalized surface text and its exact span through HIR snapshot v5, and TY consumes that declared type/span without token reconstruction. Arrow inference, implicit block returns, impl/doctrine/extern signatures, MIR body lowering, and backend behavior retain their existing semantics and remain separately bounded. | +| `task name(...) -> type { ... }` | ✅ | ✅ | Core feature. V4 stores ordinary top-level tasks as closed `explicit` / `implicit-block` / `arrow` HIR return-form facts; an explicit `-> T` carries normalized surface text and its exact span through HIR snapshot v6, and TY consumes that declared type/span without token reconstruction. Ordinary-task parameters are likewise stored as ordered HIR name/mode/lifetime/type contracts with exact spans; TY, MIR build, Meiya, and editor consumers use those semantic facts. Impl/doctrine/extern parameter signatures, arrow inference, implicit block returns, other MIR body families, and backend behavior retain their existing semantics and remain separately bounded. | | `give back` return keyword | ✅ | ✅ | | | `say` print keyword always available | ✅ | ✅ | | | String path interpolation `"{path}"` | ✅ | ✅ | Self-hosted V3 lowers resolved `IDENT(.IDENT)*` paths in every word-expression context on C and LLVM; non-path brace bodies remain literal. Executable evidence: [tests/v3_interpolation.py](tests/v3_interpolation.py) and [tests/v3_legacy_golden.py](tests/v3_legacy_golden.py). | diff --git a/freakc/auditor.py b/freakc/auditor.py index 0ea590be..673f4945 100644 --- a/freakc/auditor.py +++ b/freakc/auditor.py @@ -2878,7 +2878,7 @@ def add(label: str, ok: bool, detail: str = "") -> None: if v4_hir_task_return.exists(): hir_src = v4_hir_task_return.read_text(encoding="utf-8") for needle in ( - 'pilot v4_hir_snapshot_format = "freak-hir-snapshot-v5"', + 'pilot v4_hir_snapshot_format = "freak-hir-snapshot-v6"', 'pilot v4_hir_task_return_explicit = "explicit"', 'pilot v4_hir_task_return_implicit_block = "implicit-block"', 'pilot v4_hir_task_return_arrow = "arrow"', @@ -2935,7 +2935,7 @@ def add(label: str, ok: bool, detail: str = "") -> None: v4_task_return_readme, ( "The third bounded boundary covers declared returns on ordinary top-level tasks.", - "HIR snapshot v5 validates that vocabulary", + "HIR snapshot v6 validates that vocabulary", ), ), ( @@ -2956,7 +2956,7 @@ def add(label: str, ok: bool, detail: str = "") -> None: add( "V4 task return HIR boundary", not task_return_boundary_missing, - "HIR v5 + TY adapters + smoke + docs wired" if not task_return_boundary_missing else f"{len(task_return_boundary_missing)} gap(s)", + "HIR v6 + TY adapters + smoke + docs wired" if not task_return_boundary_missing else f"{len(task_return_boundary_missing)} gap(s)", ) if task_return_boundary_missing: failures.append( @@ -2968,6 +2968,95 @@ def add(label: str, ok: bool, detail: str = "") -> None: # Borrowed return signatures may select every parameter whose lifetime # outlives the return region. Require the set-valued TY/MIR/Meiya contract, # editor lifetime resolution, and executable source-set fixtures. + # Check 9c: ordinary-task parameter contracts belong to HIR. Nonordinary + # impl/doctrine/extern signatures remain explicit, guarded token fallbacks. + v4_hir_task_param = repo / "src" / "compiler" / "v4" / "crates" / "freak_hir" / "src" / "lib.fk" + v4_ty_task_param = repo / "src" / "compiler" / "v4" / "crates" / "freak_ty" / "src" / "lib.fk" + v4_mir_build_task_param = repo / "src" / "compiler" / "v4" / "crates" / "freak_mir_build" / "src" / "lib.fk" + v4_editor_task_param = repo / "src" / "compiler" / "v4" / "crates" / "freak_editor" / "src" / "lib.fk" + v4_task_param_smoke = repo / "src" / "compiler" / "v4" / "tests" / "task_param_semantic_boundary_smoke.fk" + task_param_boundary_missing: List[str] = [] + for path, label, needles in ( + ( + v4_hir_task_param, + "freak_hir", + ( + 'pilot v4_hir_snapshot_format = "freak-hir-snapshot-v6"', + 'pilot v4_hir_task_param_mode_value = "value"', + 'pilot v4_hir_task_param_mode_lend = "lend"', + 'pilot v4_hir_task_param_mode_lend_mut = "lend mut"', + "task v4_hir_task_param_count(", + "task v4_hir_task_param_name_span(", + "task v4_hir_task_param_segment_span(", + 'pilot out = "hir-task-param-owner"', + 'pilot out = "hir-task-param"', + "task v4_hir_snapshot_task_param_owner_is_valid(", + "task v4_hir_snapshot_task_param_is_valid(", + "task v4_hir_snapshot_task_param_slots_are_valid(", + ), + ), + ( + v4_ty_task_param, + "freak_ty", + ( + "task v4_ty_signature_is_ordinary_hir_task(", + "task v4_ty_signature_param_count(", + "task v4_ty_signature_param_name(", + "task v4_ty_signature_param_mode(", + "task v4_ty_signature_param_lifetime(", + "task v4_ty_signature_param_surface_type(", + "task v4_ty_signature_param_type_span(", + "task v4_ty_signature_param_segment_span(", + "task v4_ty_signature_param_name_span(", + "task v4_ty_nonordinary_signature_param_count_fallback(", + "task v4_ty_nonordinary_signature_param_name_fallback(", + "task v4_ty_nonordinary_signature_param_surface_type_fallback(", + ), + ), + (v4_mir_build_task_param, "freak_mir_build", ("v4_ty_signature_param_segment_span",)), + (v4_editor_task_param, "freak_editor", ("v4_ty_signature_param_name_span",)), + ): + if not path.exists(): + task_param_boundary_missing.append(f"{label}/src/lib.fk missing") + continue + source = path.read_text(encoding="utf-8") + for needle in needles: + if needle not in source: + task_param_boundary_missing.append(f"{label}: {needle}") + if not v4_task_param_smoke.exists(): + task_param_boundary_missing.append("smoke fixture: task_param_semantic_boundary_smoke.fk") + if v4_task_return_harness.exists(): + harness_src = v4_task_return_harness.read_text(encoding="utf-8") + for needle in ( + '"name": "task parameter semantic boundary"', + '"fixture": "task_param_semantic_boundary_smoke.fk"', + "def check_task_param_hir_boundary() -> None:", + "check_task_param_hir_boundary()", + ): + if needle not in harness_src: + task_param_boundary_missing.append(f"check_v4.py: {needle}") + for doc_path, needles in ( + (v4_task_return_readme, ("The fourth", "ordinary-task parameter APIs", "HIR snapshot v6 validates exact record")), + (audit_doc, ("Ordinary-task parameters are likewise stored", "Impl/doctrine/extern parameter signatures")), + ): + if not doc_path.exists(): + task_param_boundary_missing.append(f"documentation missing: {doc_path.name}") + continue + doc_src = doc_path.read_text(encoding="utf-8") + for needle in needles: + if needle not in doc_src: + task_param_boundary_missing.append(f"{doc_path.name}: {needle}") + add( + "V4 task parameter HIR boundary", + not task_param_boundary_missing, + "HIR v6 + TY/MIR/editor adapters + smoke + docs wired" if not task_param_boundary_missing else f"{len(task_param_boundary_missing)} gap(s)", + ) + if task_param_boundary_missing: + failures.append( + "V4 ordinary-task parameter HIR boundary regressed: " + + "; ".join(task_param_boundary_missing) + ) + v4_ty_lib_return = repo / "src" / "compiler" / "v4" / "crates" / "freak_ty" / "src" / "lib.fk" v4_borrowck_lib_return = repo / "src" / "compiler" / "v4" / "crates" / "freak_borrowck" / "src" / "lib.fk" v4_editor_lib_return = repo / "src" / "compiler" / "v4" / "crates" / "freak_editor" / "src" / "lib.fk" diff --git a/src/compiler/v4/README.md b/src/compiler/v4/README.md index 1049a2fe..905d89bb 100644 --- a/src/compiler/v4/README.md +++ b/src/compiler/v4/README.md @@ -82,12 +82,21 @@ that exact set and prevents local declaration lowering from returning to it. The third bounded boundary covers declared returns on ordinary top-level tasks. `freak_hir` stores one closed `explicit` / `implicit-block` / `arrow` record per task, including normalized surface type and exact contained span only for an -explicit `-> T`; HIR snapshot v5 validates that vocabulary, task-only ownership, +explicit `-> T`; HIR snapshot v6 validates that vocabulary, task-only ownership, canonical spans, contiguous slots, and declared counts before restore. TY reads explicit return types and spans only through those HIR facts. Arrow inference, implicit block returns, and non-ordinary impl/doctrine/extern signatures remain -separately named fallbacks and keep their existing semantics. Task parameter -types, shape/route fields, const annotations, non-ordinary signatures, the +separately named fallbacks and keep their existing semantics. The fourth +bounded boundary covers parameters on those same ordinary tasks. HIR owns one +ordered parameter-count record per task, including zero, plus normalized name, +`value` / `lend` / `lend mut` mode, optional named lifetime, surface type, and +their exact contained spans. TY's public ordinary-task parameter APIs consume +only those records; MIR build uses the semantic segment span and editor +definitions use the semantic name span. HIR snapshot v6 validates exact record +widths, Task-only ownership, contiguous ordinals and counts, identifier and +mode vocabulary, source ordering, and atomic restore. Impl, doctrine, and +extern signatures remain explicitly named token-facing fallbacks. Shape/route +fields, const annotations, other non-ordinary signatures, the remaining MIR body families, and all other type families remain explicit follow-up slices. These boundaries change fact ownership, not language semantics or backend representation. Symbol-valued annotated locals still @@ -518,7 +527,7 @@ unit-section||| None: "local-annotation-mir-diagnostics=0", "local-annotation-borrow-status=clean", "local-annotation-borrow-diagnostics=0", - "hir-snapshot format=freak-hir-snapshot-v5 files=1 items=1 alias-targets=0 local-annotations=4 task-returns=1 diagnostics=0", - "hir-snapshot-restore ok=1 files=1 items=1 local-annotations=4 task-returns=1 diagnostics=0 skipped-other=0 live-files=1", + "hir-snapshot format=freak-hir-snapshot-v6 files=1 items=1 alias-targets=0 local-annotations=4 task-returns=1 task-param-owners=1 task-params=0 diagnostics=0", + "hir-snapshot-restore ok=1 files=1 items=1 local-annotations=4 task-returns=1 task-param-owners=1 task-params=0 diagnostics=0 skipped-other=0 live-files=1", "local-annotation-restored-count=4", "local-annotation-restored-fixed=char", "local-annotation-malformed-restore-rejected=true", @@ -9103,8 +9103,8 @@ def check_runner_retained_memory() -> None: "task-return-mir-diagnostics=0", "task-return-borrow-status=clean", "ty-snapshot format=freak-ty-snapshot-v1 files=1 signatures=3 diagnostics=0", - "hir-snapshot format=freak-hir-snapshot-v5 files=1 items=3 alias-targets=0 local-annotations=0 task-returns=3 diagnostics=0", - "hir-snapshot-restore ok=1 files=1 items=3 local-annotations=0 task-returns=3 diagnostics=0 skipped-other=0 live-files=1", + "hir-snapshot format=freak-hir-snapshot-v6 files=1 items=3 alias-targets=0 local-annotations=0 task-returns=3 task-param-owners=3 task-params=1 diagnostics=0", + "hir-snapshot-restore ok=1 files=1 items=3 local-annotations=0 task-returns=3 task-param-owners=3 task-params=1 diagnostics=0 skipped-other=0 live-files=1", "task-return-restored-form=explicit", "task-return-restored-surface=lend 'a maybe<[word;2]>", "task-return-schema-variants-rejected=true", @@ -9126,6 +9126,51 @@ def check_runner_retained_memory() -> None: "task-return-after-editor=task changed(...) -> num", ], }, + { + "name": "task parameter semantic boundary", + "fixture": "task_param_semantic_boundary_smoke.fk", + "expect": [ + "task-param-parse-diagnostics=0", + "task-param-hir-diagnostics=0", + "task-param-empty-count=0", + "task-param-rich-hir-count=4", + "task-param-hir-borrowed-name=borrowed", + "task-param-hir-borrowed-name-source=borrowed", + "task-param-hir-borrowed-mode=lend", + "task-param-hir-borrowed-lifetime='a", + "task-param-hir-borrowed-surface=list>", + "task-param-rich-ty-count=4", + "task-param-value-name=value", + "task-param-value-mode=value", + "task-param-borrowed-mode=lend", + "task-param-borrowed-lifetime='a", + "task-param-changed-mode=lend mut", + "task-param-mir-value-name=value", + "task-param-mir-span-semantic=true", + "task-param-meiya-status=clean", + "task-param-editor-label-definition=true", + "hir-snapshot format=freak-hir-snapshot-v6", + "task-param-restored-count=4", + "task-param-schema-variants-rejected=true", + "task-param-schema-variants-atomic=true", + "task-param-invalid-no-invented=true", + "task-param-anonymous-normalized=true", + "task-param-static-preserved=true", + "task-param-doctrine-fallback=true", + "task-param-impl-fallback=true", + "task-param-extern-fallback=true", + "task-param-invalidation-hir=true", + "task-param-invalidation-ty=true", + "task-param-invalidation-mir=true", + "task-param-invalidation-borrowck=true", + "task-param-invalidation-editor=true", + "task-param-invalidation-after-hir=num", + "task-param-invalidation-after-ty=num", + "task-param-invalidation-after-mir=num", + "task-param-invalidation-after-borrow=clean", + "task-param-invalidation-after-editor=num", + ], + }, ] if str(ROOT) not in sys.path: @@ -9772,7 +9817,7 @@ def check_mir_local_annotation_boundary() -> None: violations: list[str] = [] for marker in ( - 'pilot v4_hir_snapshot_format = "freak-hir-snapshot-v5"', + 'pilot v4_hir_snapshot_format = "freak-hir-snapshot-v6"', "pilot v4_hir_local_annotation_items = 0", "pilot v4_hir_local_annotation_stmt_spans = 0", "pilot v4_hir_local_annotation_types = 0", @@ -9894,7 +9939,7 @@ def check_task_return_hir_boundary() -> None: violations.append("task return boundary unexpectedly changed the TY snapshot format") for marker in ( - 'pilot v4_hir_snapshot_format = "freak-hir-snapshot-v5"', + 'pilot v4_hir_snapshot_format = "freak-hir-snapshot-v6"', "pilot v4_hir_task_return_items = 0", "pilot v4_hir_task_return_forms = 0", "pilot v4_hir_task_return_types = 0", @@ -10038,6 +10083,183 @@ def check_task_return_hir_boundary() -> None: print("no syntax past HIR: ordinary task declared return type and span") +def task_param_ordinary_call_closure_violations(ty_source: str) -> list[str]: + violations: list[str] = [] + public_contracts = { + "v4_ty_signature_param_count": "v4_hir_task_param_count", + "v4_ty_signature_param_name": "v4_hir_task_param_name", + "v4_ty_signature_param_mode": "v4_hir_task_param_mode", + "v4_ty_signature_param_lifetime": "v4_hir_task_param_lifetime", + "v4_ty_signature_param_lifetime_span": "v4_hir_task_param_lifetime_span", + "v4_ty_signature_param_surface_type": "v4_hir_task_param_surface_type", + "v4_ty_signature_param_type_span": "v4_hir_task_param_type_span", + "v4_ty_signature_param_segment_span": "v4_hir_task_param_segment_span", + "v4_ty_signature_param_name_span": "v4_hir_task_param_name_span", + } + reached: set[str] = set() + ordinary_marker = "if v4_ty_signature_is_ordinary_hir_task(ty_id, sig_id)" + + for task_name, hir_accessor in public_contracts.items(): + body = freak_task_body(ty_source, task_name) + ordinary_arm = None if body is None else freak_braced_arm(body, ordinary_marker) + if ordinary_arm is None: + violations.append( + f"task parameter TY adapter has no bounded ordinary-task arm: {task_name}" + ) + continue + if hir_accessor not in ordinary_arm: + violations.append( + f"task parameter ordinary arm does not consume {hir_accessor}: {task_name}" + ) + reached.update( + freak_task_call_closure( + ty_source, + freak_task_calls(ty_source, ordinary_arm), + ) + ) + + forbidden_fragments = ( + "v4_ty_nonordinary_signature_param_", + "v4_ty_type_text", + "v4_lex_", + "v4_parse_", + "v4_expand_", + "v4_ty_span_from_tokens", + "_token", + ) + for task_name in sorted(reached): + body = freak_task_body(ty_source, task_name) or "" + for forbidden in forbidden_fragments: + if forbidden in task_name or forbidden in body: + violations.append( + f"task parameter ordinary HIR call closure reconstructs syntax: " + f"{task_name} uses {forbidden}" + ) + + return violations + + +def check_task_param_hir_boundary() -> None: + hir_source = read_text(crate_path("freak_hir")) + ty_source = read_text(crate_path("freak_ty")) + mir_build_source = read_text(crate_path("freak_mir_build")) + editor_source = read_text(crate_path("freak_editor")) + violations: list[str] = [] + + for marker in ( + 'pilot v4_hir_snapshot_format = "freak-hir-snapshot-v6"', + 'pilot v4_hir_task_param_mode_value = "value"', + 'pilot v4_hir_task_param_mode_lend = "lend"', + 'pilot v4_hir_task_param_mode_lend_mut = "lend mut"', + '"hir-task-param-owner"', + '"hir-task-param"', + '"task-param-owners"', + '"task-params"', + "task v4_hir_snapshot_task_param_owner_is_valid(", + "task v4_hir_snapshot_task_param_is_valid(", + "task v4_hir_snapshot_task_param_slots_are_valid(", + ): + if marker not in hir_source: + violations.append(f"task parameter HIR boundary missing: {marker}") + + hir_accessors = ( + "v4_hir_task_param_count", + "v4_hir_task_param_name", + "v4_hir_task_param_name_span", + "v4_hir_task_param_mode", + "v4_hir_task_param_lifetime", + "v4_hir_task_param_lifetime_span", + "v4_hir_task_param_surface_type", + "v4_hir_task_param_type_span", + "v4_hir_task_param_segment_span", + ) + for task_name in hir_accessors: + body = freak_task_body(hir_source, task_name) + if body is None: + violations.append(f"task parameter HIR storage accessor missing: {task_name}") + continue + for forbidden in ("v4_parse_", "v4_lex_", "v4_expand_", "_token"): + if forbidden in body: + violations.append( + f"task parameter HIR accessor reconstructs syntax: {task_name} uses {forbidden}" + ) + + public_contracts = { + "v4_ty_signature_param_count": ("v4_hir_task_param_count", "v4_ty_nonordinary_signature_param_count_fallback"), + "v4_ty_signature_param_name": ("v4_hir_task_param_name", "v4_ty_nonordinary_signature_param_name_fallback"), + "v4_ty_signature_param_mode": ("v4_hir_task_param_mode", "v4_ty_nonordinary_signature_param_mode_fallback"), + "v4_ty_signature_param_lifetime": ("v4_hir_task_param_lifetime", "v4_ty_nonordinary_signature_param_lifetime_fallback"), + "v4_ty_signature_param_lifetime_span": ("v4_hir_task_param_lifetime_span", "v4_ty_nonordinary_signature_param_lifetime_span_fallback"), + "v4_ty_signature_param_surface_type": ("v4_hir_task_param_surface_type", "v4_ty_nonordinary_signature_param_surface_type_fallback"), + "v4_ty_signature_param_type_span": ("v4_hir_task_param_type_span", "v4_ty_nonordinary_signature_param_type_span_fallback"), + "v4_ty_signature_param_segment_span": ("v4_hir_task_param_segment_span", "v4_ty_nonordinary_signature_param_segment_span_fallback"), + "v4_ty_signature_param_name_span": ("v4_hir_task_param_name_span", "v4_ty_nonordinary_signature_param_name_span_fallback"), + } + for task_name, required in public_contracts.items(): + body = freak_task_body(ty_source, task_name) + if body is None: + violations.append(f"task parameter TY public adapter missing: {task_name}") + continue + if "v4_ty_signature_is_ordinary_hir_task" not in body: + violations.append(f"task parameter TY adapter has no ordinary HIR dispatch: {task_name}") + for needle in required: + if needle not in body: + violations.append(f"task parameter TY adapter missing {needle}: {task_name}") + for forbidden in ("v4_lex_", "v4_parse_", "v4_expand_", "v4_ty_type_text"): + if forbidden in body: + violations.append(f"ordinary task parameter adapter reconstructs syntax: {task_name} uses {forbidden}") + + type_body = freak_task_body(ty_source, "v4_ty_signature_param_type") + if type_body is None or "v4_ty_signature_param_surface_type" not in type_body: + violations.append("task parameter canonical type does not derive from semantic surface type") + + ordinary_body = freak_task_body(ty_source, "v4_ty_signature_is_ordinary_hir_task") + if ordinary_body is None or "v4_hir_item_is_ordinary_task" not in ordinary_body: + violations.append("task parameter ordinary discriminator bypasses HIR ownership") + if ordinary_body is not None: + for forbidden in ("v4_lex_", "v4_parse_", "v4_expand_", "_token"): + if forbidden in ordinary_body: + violations.append(f"task parameter ordinary discriminator reconstructs syntax: {forbidden}") + + lower_body = freak_task_body(mir_build_source, "v4_mir_seed_signature_params") + if lower_body is None or "v4_ty_signature_param_segment_span" not in lower_body: + violations.append("MIR build does not consume semantic parameter segment spans") + editor_body = freak_task_body(editor_source, "v4_editor_signature_param_name_span") + if editor_body is None or "v4_ty_signature_param_name_span" not in editor_body: + violations.append("editor parameter definitions do not consume semantic name spans") + + violations.extend(task_param_ordinary_call_closure_violations(ty_source)) + + param_count_body = freak_task_body(ty_source, "v4_ty_signature_param_count") + canonical_count_return = ( + "give back v4_hir_task_param_count(v4_ty_signature_hir_id(ty_id), " + "v4_ty_signature_hir_item(ty_id, sig_id))" + ) + if param_count_body is None or canonical_count_return not in param_count_body: + violations.append("task parameter boundary guard self-test could not locate ordinary count return") + else: + mutated_body = param_count_body.replace( + canonical_count_return, + "give back v4_ty_nonordinary_signature_param_count_fallback(ty_id, sig_id)", + 1, + ) + mutated_source = ty_source.replace(param_count_body, mutated_body, 1) + probe_violations = task_param_ordinary_call_closure_violations(mutated_source) + if not any( + "v4_ty_nonordinary_signature_param_" in violation + for violation in probe_violations + ): + violations.append("task parameter boundary guard self-test accepted ordinary fallback") + + if violations: + for violation in violations: + print(violation) + raise SystemExit(1) + + print("task parameter boundary guard self-test: ordinary fallback rejected") + print("no syntax past HIR: ordinary task parameter contracts and spans") + + def check_tooling_interfaces() -> None: readme = read_text(V4_ROOT / "README.md") lsp_source = read_text(crate_path("freak_lsp")) @@ -11501,6 +11723,7 @@ def main(argv: list[str] | None = None) -> int: check_alias_hir_boundary() check_mir_local_annotation_boundary() check_task_return_hir_boundary() + check_task_param_hir_boundary() check_tooling_interfaces() check_snapshot_inventories() base_source = check_flattened_crates() diff --git a/src/compiler/v4/crates/freak_hir/src/lib.fk b/src/compiler/v4/crates/freak_hir/src/lib.fk index 52fea219..8fb1e90b 100644 --- a/src/compiler/v4/crates/freak_hir/src/lib.fk +++ b/src/compiler/v4/crates/freak_hir/src/lib.fk @@ -1758,8 +1758,8 @@ task v4_hir_snapshot_task_param_owner_line(hir_id: int, record_id: int) -> word pilot out = "hir-task-param-owner" out = out + "|" + word_from_int(hir_id) out = out + "|" + word_from_int(record_id) - out = out + "|" + array_get(v4_hir_task_param_owner_items_handle(hir_id), record_id) - out = out + "|" + array_get(v4_hir_task_param_owner_counts_handle(hir_id), record_id) + out = out + "|" + word_from_int(word_to_int(array_get(v4_hir_task_param_owner_items_handle(hir_id), record_id))) + out = out + "|" + word_from_int(word_to_int(array_get(v4_hir_task_param_owner_counts_handle(hir_id), record_id))) give back out } @@ -1767,8 +1767,8 @@ task v4_hir_snapshot_task_param_line(hir_id: int, record_id: int) -> word { pilot out = "hir-task-param" out = out + "|" + word_from_int(hir_id) out = out + "|" + word_from_int(record_id) - out = out + "|" + array_get(v4_hir_task_param_items_handle(hir_id), record_id) - out = out + "|" + array_get(v4_hir_task_param_ordinals_handle(hir_id), record_id) + out = out + "|" + word_from_int(word_to_int(array_get(v4_hir_task_param_items_handle(hir_id), record_id))) + out = out + "|" + word_from_int(word_to_int(array_get(v4_hir_task_param_ordinals_handle(hir_id), record_id))) out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_names_handle(hir_id), record_id)) out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_name_spans_handle(hir_id), record_id)) out = out + "|" + v4_hir_snapshot_escape(array_get(v4_hir_task_param_modes_handle(hir_id), record_id)) diff --git a/src/compiler/v4/crates/freak_mir_build/src/lib.fk b/src/compiler/v4/crates/freak_mir_build/src/lib.fk index 861971d9..2121c77b 100644 --- a/src/compiler/v4/crates/freak_mir_build/src/lib.fk +++ b/src/compiler/v4/crates/freak_mir_build/src/lib.fk @@ -8638,15 +8638,15 @@ task v4_mir_lower_task_body_tokens(mir_id: int, body_id: int, stream_id: int, it v4_mir_lower_task_body_token_range(mir_id, body_id, stream_id, start_token, end_token, item_span) } -task v4_mir_seed_param_local(mir_id: int, body_id: int, param_name: word, param_ty: word, param_mode: word, item_span: word, duplicate_help: word) -> void { +task v4_mir_seed_param_local(mir_id: int, body_id: int, param_name: word, param_ty: word, param_mode: word, param_span: word, scope_span: word, duplicate_help: word) -> void { if param_name == "" { give back } - if v4_mir_find_local_visible_at(mir_id, body_id, param_name, v4_span_start(item_span)) >= 0 { - v4_mir_add_type_error(mir_id, item_span, "duplicate parameter binding", param_name + " already exists in " + duplicate_help) + if v4_mir_find_local_visible_at(mir_id, body_id, param_name, v4_span_start(param_span)) >= 0 { + v4_mir_add_type_error(mir_id, param_span, "duplicate parameter binding", param_name + " already exists in " + duplicate_help) give back } - pilot local_id = v4_mir_add_local(mir_id, body_id, param_name, param_ty, item_span) + pilot local_id = v4_mir_add_local_at_scope(mir_id, body_id, param_name, param_ty, param_span, scope_span) v4_mir_set_local_mode(mir_id, body_id, local_id, param_mode) } @@ -8663,7 +8663,7 @@ task v4_mir_seed_signature_params(mir_id: int, body_id: int, ty_id: int, sig_id: if param_span == no_span { param_span = item_span } - v4_mir_seed_param_local(mir_id, body_id, param_name, param_ty, param_mode, param_span, "this signature") + v4_mir_seed_param_local(mir_id, body_id, param_name, param_ty, param_mode, param_span, item_span, "this signature") } param_idx += 1 } @@ -8677,7 +8677,7 @@ task v4_mir_seed_impl_method_params(mir_id: int, body_id: int, ty_id: int, hir_i if param_name != "" { pilot param_ty = v4_ty_impl_method_param_type(ty_id, hir_item, method_id, param_idx) pilot param_mode = v4_ty_impl_method_param_mode(ty_id, hir_item, method_id, param_idx) - v4_mir_seed_param_local(mir_id, body_id, param_name, param_ty, param_mode, item_span, "this method signature") + v4_mir_seed_param_local(mir_id, body_id, param_name, param_ty, param_mode, item_span, item_span, "this method signature") } param_idx += 1 } diff --git a/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk b/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk index 877b9103..b6901731 100644 --- a/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk +++ b/src/compiler/v4/tests/task_param_semantic_boundary_smoke.fk @@ -35,12 +35,7 @@ task v4_task_param_offset(stream_id: int, value: word, ordinal: int) -> int { task v4_task_param_source_text() -> word { pilot src = "task empty() -> int " + v4_task_param_braces(" give back 0 ") + "\n" - src = src + "task rich<'a>(\n" - src = src + " value: maybe<(word, [int; 2])>,\n" - src = src + " lend 'a borrowed: list>,\n" - src = src + " lend mut 'a changed: [int; 2],\n" - src = src + " matrix: [[int; 2]; 3]\n" - src = src + ") -> int " + v4_task_param_braces(" give back 7 ") + "\n" + src = src + "task rich<'a>(value: maybe<(word, [int; 2])>, lend 'a borrowed: list>, lend mut 'a changed: [int; 2], matrix: [[int; 2]; 3]) -> int " + v4_task_param_braces(" give back 7 ") + "\n" src = src + "task named(value: int) -> int " + v4_task_param_braces(" give back value ") + "\n" src = src + "task caller() -> int " + v4_task_param_braces(" give back named(value: 7) ") + "\n" give back src @@ -249,17 +244,13 @@ task v4_task_param_find_hir_item(hir_id: int, kind: word, name: word) -> int { task v4_task_param_residual_hir_probe() -> void { pilot src = "task anonymous(lend '_ borrowed: word) -> int " + v4_task_param_braces(" give back 0 ") + "\n" src = src + "task immortal(lend 'static borrowed: word) -> int " + v4_task_param_braces(" give back 0 ") + "\n" - src = src + "task curly(value: Box<" + v4_task_param_braces("left:int,right:int") + ",word>) -> int " + v4_task_param_braces(" give back 0 ") + "\n" pilot stream_id = v4_lex_text(42, src) pilot tree_id = v4_parse_stream(42, stream_id) pilot hir_id = v4_hir_lower_tree(42, tree_id) pilot anonymous_item = v4_task_param_find_hir_item(hir_id, v4_hir_task, "anonymous") pilot immortal_item = v4_task_param_find_hir_item(hir_id, v4_hir_task, "immortal") - pilot curly_item = v4_task_param_find_hir_item(hir_id, v4_hir_task, "curly") - pilot curly_type = "Box<" + v4_task_param_braces("left:int,right:int") + ",word>" say "task-param-anonymous-normalized=" + v4_task_param_bool(v4_hir_task_param_lifetime(hir_id, anonymous_item, 0) == "" and v4_hir_task_param_lifetime_span(hir_id, anonymous_item, 0) == V4_NO_SPAN) say "task-param-static-preserved=" + v4_task_param_bool(v4_hir_task_param_lifetime(hir_id, immortal_item, 0) == "'static" and v4_hir_task_param_lifetime_span(hir_id, immortal_item, 0) != V4_NO_SPAN) - say "task-param-curly-nesting=" + v4_task_param_bool(v4_hir_task_param_count(hir_id, curly_item) == 1 and v4_hir_task_param_surface_type(hir_id, curly_item, 0) == curly_type) } task v4_task_param_nonordinary_probe() -> void { @@ -315,6 +306,11 @@ pilot v4_task_param_hir_borrowed_type_span = v4_hir_task_param_type_span(v4_task pilot v4_task_param_hir_borrowed_segment_span = v4_hir_task_param_segment_span(v4_task_param_hir, v4_task_param_rich_item, 1) say "task-param-parse-diagnostics=" + word_from_int(v4_parse_diag_count(v4_task_param_tree)) +pilot v4_task_param_parse_diag_id = 0 +repeat until v4_task_param_parse_diag_id >= v4_parse_diag_count(v4_task_param_tree) { + say "task-param-parse-diagnostic=" + v4_parse_diag(v4_task_param_tree, v4_task_param_parse_diag_id) + v4_task_param_parse_diag_id += 1 +} say "task-param-hir-diagnostics=" + word_from_int(v4_hir_diag_count(v4_task_param_hir)) say "task-param-empty-count=" + word_from_int(v4_hir_task_param_count(v4_task_param_hir, v4_task_param_empty_item)) say "task-param-rich-hir-count=" + word_from_int(v4_hir_task_param_count(v4_task_param_hir, v4_task_param_rich_item)) diff --git a/src/compiler/v4/tests/task_return_semantic_boundary_smoke.fk b/src/compiler/v4/tests/task_return_semantic_boundary_smoke.fk index 95b12277..d462fa2a 100644 --- a/src/compiler/v4/tests/task_return_semantic_boundary_smoke.fk +++ b/src/compiler/v4/tests/task_return_semantic_boundary_smoke.fk @@ -201,6 +201,11 @@ say "task-return-ty-canonical=" + v4_ty_signature_return_type(v4_task_return_ty, say "task-return-ty-display=" + v4_ty_signature_of(v4_task_return_ty, v4_task_return_keep_def) say "task-return-mir-expected=" + v4_mir_expected_return_type(v4_task_return_mir, v4_task_return_keep_body) say "task-return-mir-diagnostics=" + word_from_int(v4_mir_diag_count(v4_task_return_mir)) +pilot v4_task_return_mir_diag_id = 0 +repeat until v4_task_return_mir_diag_id >= v4_mir_diag_count(v4_task_return_mir) { + say "task-return-mir-diagnostic=" + v4_mir_diag(v4_task_return_mir, v4_task_return_mir_diag_id) + v4_task_return_mir_diag_id += 1 +} say "task-return-borrow-status=" + v4_borrowck_result_status(v4_task_return_borrow, v4_task_return_keep_result) say v4_ty_snapshot_summary() From 8445f7fccb42175ffd3bb565d1655e2ec6c262ea Mon Sep 17 00:00:00 2001 From: TeRiRi_606 <147689545+OttoApocalypse69@users.noreply.github.com> Date: Thu, 13 Aug 2026 21:16:48 +0300 Subject: [PATCH 5/5] Align task parameter audit ordering Place the ordinary parameter HIR check before the contract-region section it precedes. --- freakc/auditor.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freakc/auditor.py b/freakc/auditor.py index 673f4945..62cbc326 100644 --- a/freakc/auditor.py +++ b/freakc/auditor.py @@ -2964,10 +2964,6 @@ def add(label: str, ok: bool, detail: str = "") -> None: + "; ".join(task_return_boundary_missing) ) - # ── Check 10: V4 contract-region source sets ── - # Borrowed return signatures may select every parameter whose lifetime - # outlives the return region. Require the set-valued TY/MIR/Meiya contract, - # editor lifetime resolution, and executable source-set fixtures. # Check 9c: ordinary-task parameter contracts belong to HIR. Nonordinary # impl/doctrine/extern signatures remain explicit, guarded token fallbacks. v4_hir_task_param = repo / "src" / "compiler" / "v4" / "crates" / "freak_hir" / "src" / "lib.fk" @@ -3057,6 +3053,10 @@ def add(label: str, ok: bool, detail: str = "") -> None: + "; ".join(task_param_boundary_missing) ) + # ── Check 10: V4 contract-region source sets ── + # Borrowed return signatures may select every parameter whose lifetime + # outlives the return region. Require the set-valued TY/MIR/Meiya contract, + # editor lifetime resolution, and executable source-set fixtures. v4_ty_lib_return = repo / "src" / "compiler" / "v4" / "crates" / "freak_ty" / "src" / "lib.fk" v4_borrowck_lib_return = repo / "src" / "compiler" / "v4" / "crates" / "freak_borrowck" / "src" / "lib.fk" v4_editor_lib_return = repo / "src" / "compiler" / "v4" / "crates" / "freak_editor" / "src" / "lib.fk"