From f2cbb658e11d43dafaa08b54397c942bf8ac340a Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 10 Oct 2026 14:00:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(stubgen):=20vpi=20=E8=90=BD=E7=9B=98?= =?UTF-8?q?=E5=85=A5=E5=8F=A3=E7=BB=9F=E4=B8=80=E9=87=8D=E5=BB=BA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=BA=A7=E5=90=8D=E5=AD=97=E7=AA=97=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20FileFuncNames=20=E6=82=AC=E5=9E=82?= =?UTF-8?q?=E9=87=8E=E8=AF=BB=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase1 1b-pre / 1b 兜底 / BuildPipeline / Repl 为生成 vpi 各自重新 parse 出独立 AST,但不走 register_file_funcs,导致 is_file_func(range)(_PushInductionEntry)仍读到上一个文件的表 + 已被 reset 的池 → 悬垂指针,ASan access-violation 崩在 HashTable._slot_hash。将 reset_file_name_window + register_file_func_names 收敛到 _GeneratePyiFromAst 唯一入口,覆盖全部 vpi 落盘调用点;Phase2 的重复调用随之移除。 --- App/lib/Phase/Phase2/__init__.vp | 8 ++------ App/lib/Stub/StubGen/Converter.vp | 10 ++++++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/App/lib/Phase/Phase2/__init__.vp b/App/lib/Phase/Phase2/__init__.vp index 7e2b1bf..b80f416 100644 --- a/App/lib/Phase/Phase2/__init__.vp +++ b/App/lib/Phase/Phase2/__init__.vp @@ -679,12 +679,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou continue pyi_buf_vp2: bytes = stdlib.malloc(PYI_BUF_SIZE_P2) if pyi_buf_vp2 is not None: - # 文件级名字窗口:本阶段为生成 vpi 重新解析出 tree_vp2,但**不走** register_file_funcs; - # 而 _PyiFunction → compute_escape_summary → _ScanEscapes → _PushInductionEntry 会问 - # is_file_func("range")。不清窗口就会读到"上一个文件的表 + 已被 reset 的池"→ - # 悬垂指针(ASan access-violation / 非 ASan 静默错答)。见 StructGenMixin.reset_file_name_window。 - GenApi.reset_file_name_window() - GenApi.register_file_func_names(mb, tree_vp2) + # 文件级名字窗口(FileFuncNames 等)由 _GeneratePyiFromAst 入口统一 reset+重建, + # 不再在此处重复调用;契约见 StructGenMixin.reset_file_name_window。 pyi_pos_vp2: sizet = StubConverter._GeneratePyiFromAst(mb, tree_vp2, ent_vp2.Path, pyi_buf_vp2, PYI_BUF_SIZE_P2) if pyi_pos_vp2 > 0: pyi_path_vp2: str = StubMergerCollect._sliced_path(temp_dir, td_len_vpa, ent_vp2.Sha1, "vpi") diff --git a/App/lib/Stub/StubGen/Converter.vp b/App/lib/Stub/StubGen/Converter.vp index 6f58951..59f91f8 100644 --- a/App/lib/Stub/StubGen/Converter.vp +++ b/App/lib/Stub/StubGen/Converter.vp @@ -708,6 +708,16 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*, rel_path: str, buf # an absolute path (fatal_error opens it directly). Set once at entry to cover all branches. if rel_path is not None: GenApi.set_current_file_type(rel_path) + # 文件级名字窗口:本函数是 vpi 落盘的**唯一入口**,而各调用方只为落盘各自重新 parse 出 + # 独立 AST、**不走** register_file_funcs。但 _PyiFunction → compute_escape_summary → + # _ScanEscapes → _PushInductionEntry 会问 is_file_func("range")("本文件自己定义过 range + # 就放弃区间推断")。若不清窗口再重建表,就会读到"上一个文件的表 + 已被 reset 的池" = + # 悬垂指针(ASan access-violation 崩在 HashTable._slot_hash / 非 ASan 静默错答)。 + # 契约见 StructGenMixin.reset_file_name_window:任何文件级入口必须先清再重建。 + # 收敛到本入口可一次性覆盖 Phase1 1b-pre / Phase1 1b 兜底 / BuildPipeline / Repl / Phase2。 + GenApi.reset_file_name_window() + GenApi.register_file_func_names(mb, tree) + pos: sizet = 0 # Pre-pass: register this file's CDefines into the _g_pyi cache in declaration order