From 086e792b306b04c6c6aa12b229acea1e5f58c7d6 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 20 Aug 2026 11:14:26 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20=E5=85=84=E5=BC=9F=20Mixin=20?= =?UTF-8?q?=E5=85=9C=E5=BA=95=E8=BF=87=E6=BB=A4=E6=B3=9B=E5=9E=8B=E7=89=B9?= =?UTF-8?q?=E5=8C=96=E7=B1=BB=E5=90=8D=E2=80=94=E2=80=94=E9=98=B2=E8=AF=AF?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=20list=20=E7=89=B9=E5=8C=96=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Config.vp Load_project_config 的 root.__getitem__(JsonValue 方法)在 found_func 未命中时被兄弟兜底遍历 struct 表误绑定到 list[ASTptr].__getitem__(泛型特化函数在模块中存在),this 按 list 布局前移 sizeof(list) → 运行期读 -1 崩溃。兜底现仅对不含 '[' 的普通类名生效,对齐 TPC 侧 class_methods 校验语义。 --- App/lib/core/Gen/CallGenCall.vp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/App/lib/core/Gen/CallGenCall.vp b/App/lib/core/Gen/CallGenCall.vp index 758fff2..c445269 100644 --- a/App/lib/core/Gen/CallGenCall.vp +++ b/App/lib/core/Gen/CallGenCall.vp @@ -636,6 +636,13 @@ class CallGenCall(CallGenBase.CallGenBase): # (如 BaseB 内 self.helper() 调兄弟 BaseA.helper,BaseB 无 BaseA 的 # 继承信息)。遍历已注册 struct 表找定义类方法,this 由下方 # _adjust_this_for_inherited_method 按组合布局前移 sizeof(定义类)。 + # 注意:仅对普通类名兜底——泛型特化类名(list[X] / dict[K,V])是 + # 模板生成的特殊容器,其特化函数(如 list[ASTptr].__getitem__)虽 + # 在模块中存在,但绝非"兄弟 Mixin"(NoVTableCrossMixinTest 的 + # BaseA/BaseB/Combined 场景)。若不过滤,JsonValue.__getitem__ 等 + # 普通方法调用在 found_func 未命中时会误绑定到 list 特化函数, + # this 按 list 布局前移 sizeof(list) → 运行期读 -1 崩溃 + # (Config.vp Load_project_config root.__getitem__ 根因)。 if found_func is None: sc_i: int = 0 sc_n: int = HandlesStruct.get_struct_count() @@ -644,6 +651,11 @@ class CallGenCall(CallGenBase.CallGenBase): if cand_entry is not None and cand_entry.Name is not None: cand_name: str = cand_entry.Name if string.strcmp(cand_name, class_name) != 0: + # 泛型特化类名含 '['(list[...]/dict[...]):跳过, + # 不是兄弟 Mixin 候选(见上方注释) + if string.strchr(cand_name, '[') is not None: + sc_i += 1 + continue cand_lookup: str = pool.alloc(128) if cand_lookup is not None: viperlib.snprintf(cand_lookup, 128, "%s.%s", cand_name, method_name)