fix(transpyv): 消除隐式向下转型(ast.AST* 实参 → 派生 AST 形参)

c 源码违规(严格指针规则:基类指针传派生类形参属向下转型,须显式转换):

1) TranslatorGenMixin._prescan_funcdef_signatures:形参由 ast.FunctionDef* 改为
   ast.AST*,函数体内显式 `fd: ast.FunctionDef* = ast.FunctionDef*(node)`。
   理由:模块级调度器只持有 ast.AST* 子节点,同一处调用的
   translate_function_def / translate_class_def / _register_cexport_from_funcdef
   形参一律是 ast.AST*,本函数是唯一例外(报错现场:第 2 个实参 %"..AST"* 不能
   隐式转为形参 %"..FunctionDef"*)。改为与兄弟入口同口径,调用点无需改动。

2) CallGenDispatch len() 内置分支:_is_list_builtin_receiver 第 5 形参是
   ast.Call*(仅用于 D25 fail-fast 定位节点),实参 len_arg_node 声明为基类
   ast.AST* ⇒ 显式窄化 `len_arg_cl: ast.Call* = ast.Call*(len_arg_node)`。

附:对 App\lib 全量静态扫描(core\Gen 全 47 文件 + Stub/Phase/core/main)确认
此类「基类指针实参 → 派生形参」的隐式向下转型仅此两处,其余调用点均为同类型
或向上转型(规则允许)。

同文件另含仓库内既有书写整理(续行合并),无行为变化。
This commit is contained in:
TermiNexus committed 2026-09-28 20:20:56 +08:00
1 parent af5fba81c5
commit 75ea6fb9b2
2 files changed
+20 -9

No files matched your search

+11 -7
View File
@@ -18,10 +18,10 @@ import lib.core.Gen.Type.TypeSpec as TSpec
import lib.Stub.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
from . import CallGenBase
import lib.core.Gen.GenApi as GenApi
# ============================================================
import lib.core.Gen.GenApi as GenApi
# ============================================================
# CallGenDispatch - CallGenMixin 拆分(阶段 C):translate_call 检测段
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
@@ -813,15 +813,19 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
# - 普通类:调用 {Class}.__len__ 函数
# - 都没有:fatal_error
# str(Ptr(Int8))保持 strlen(内建语义)。
len_struct_ty: llvmlite.LLVMType* = \
self.Gen.StructGen.get_struct_type_from_value(len_val)
len_struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type_from_value(len_val)
if len_struct_ty is not None:
len_cls_nm: str = self.Gen.StructGen.get_class_name_by_type(pool, len_struct_ty)
if len_cls_nm is None:
self.Gen.TypeGenErr.fatal_error(len_arg_node, "len() 参数类型推断失败(结构体类名未知)", "TypeError")
# list 内置 __len__:读 __count__(GEP 偏移 1,i64)
# 判据优先取接收者实际类型(_is_list_builtin_receiver)
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, len_val, len_cls_nm, "__len__", len_arg_node) != 0:
# 目标类型已由 can==1(len 的实参存在)确定为表达式节点
# ⇒ 在此显式窄化:形参是 ast.Call*(仅用于 fail-fast
# 定位节点),而 len_arg_node 声明为基类 ast.AST*;
# 基类指针传派生类形参属向下转型,严格指针规则下禁止。
len_arg_cl: ast.Call* = ast.Call*(len_arg_node)
if self.Gen.CallGenProp._is_list_builtin_receiver(pool, len_val, len_cls_nm, "__len__", len_arg_cl) != 0:
i64_ty_lb: llvmlite.LLVMType* = llvmlite.Int64(pool)
idx_one_lb: llvmlite.Value* = llvmlite.const_int64(pool, 1)
cnt_ptr_lb: llvmlite.Value* = llvmlite.build_gep(builder, i64_ty_lb, len_val, idx_one_lb)
+9 -2
View File
@@ -133,9 +133,16 @@ novirtual class TranslatorGenMixin:
# 避免 Phase2 翻译 App 文件时访问悬空结构体(UAF)。
# 仅解析类型触发特化,不验证结果(1b 全量翻译时重新解析)。
# ============================================================
def _prescan_funcdef_signatures(self, trans: HT.Translator*, fd: ast.FunctionDef*) -> None:
def _prescan_funcdef_signatures(self, trans: HT.Translator*, node: ast.AST*) -> None:
"""预解析模块级函数签名的返回/参数类型,触发泛型类特化"""
if trans is None or fd is None:
if trans is None or node is None:
return
# 入口收基类 ast.AST*(模块级调度器只持有 ast.AST* 子节点,与同一处调用的
# translate_function_def / translate_class_def / _register_cexport_from_funcdef
# 形参口径一致),在此显式窄化为 ast.FunctionDef*:基类指针传派生类形参属
# 向下转型,严格指针规则下禁止隐式转换。
fd: ast.FunctionDef* = ast.FunctionDef*(node)
if fd is None:
return
pool: memhub.MemBuddy* = trans.Pool
if pool is None: