fix(TPV/CallGenBase): text.ll 返回类型的命名指针不再坍缩成通用 i8*,修 FakeDuck parts[0] 报整数隐式转指针
现象(TransPyV 编译 Test/FakeDuckTest):
main.vp:115 p0: str = parts[0]
CastError: 整数隐式转指针已禁止…出错表达式: 下标表达式 Subscript
(parts = s1.split(','),s1: str,split 由 includes/_fakeduck.vp 的 _str 提供)
根因链(逐环取证,均落在产物文件上):
1. _fakeduck.vp:273 `def split(self, delimiter: str) -> list[str]*`。
2. 定义侧产物正确:temp/88/884eaabef9bd161c.text.ll:1775
define %"b0798adca340002b.list[str]"* @"884eaabef9bd161c._str.split"(...)
(884eaabef9bd161c = includes/_fakeduck.vp,b0798adca340002b = includes/_list.vp)
3. 调用侧 declare 走了 vpi 注解:temp/88/884eaabef9bd161c.vpi:27
def split(self, delimiter: str) -> list[str] | t.CPtr: pass
该联合在 stub 侧解析不出 `list[str]` 这个泛型特化名 ⇒ 坍缩成 i8*(既有设计已知的
「跨模块 declare 的 list[T] 返回类型被简化」),故 _translate_fakeduck_call 里那条
「从定义模块 text.ll 读精确返回类型」的兜底(CallGenFd.vp:134-142)必须生效。
4. 但该兜底读到的 `%"b0798adca340002b.list[str]"*` 又被本函数坍缩回 i8*:
CallGenBase._ParseLLVMRetTyStr 的「含 * 者一律返回通用 Ptr(Int8)」分支
(原注释:"包括 i8*, i32*, %"name"*, { i32, i8 }* 等")。
5. 于是 parts 的 alloca 退化为 i8* ⇒ parts[0] 走字节下标取到整数 ⇒ 赋给 str 报
「整数隐式转指针已禁止」(报文指不到真因,正是本问题最难查的地方)。
改动(CallGenBase._ParseLLVMRetTyStr):
- 新增「命名类型 `%"name"*` / `%name*`」分支:剥引号/空格与尾随 `*`(支持多级),
先 GenApi.get_struct_type(name)、未命中再 GenApi.get_enum_base_type(name),命中即
按星号层数包 Ptr 返回真实结构体/枚举指针;查不到登记项时才保持原来的通用 Ptr(Int8)
行为(名字可能来自尚未登记的模块,不引入新的静默降级面)。
- 同步更新该函数顶部说明(原写「含 * 者返回通用 Ptr(Int8)」,现区分字面量结构体 /
命名类型 / 其余)。
- 收益面不限 FakeDuck:所有经 text.ll 取返回类型的方法调用(CallGenCall / CallGenDispatch
/ CallGenProp / CallGenFd 等)都从「指针一律 i8*」变为「命名类指针精确」,
调用方 alloca 与下标/字段语义不再退化。
待验证(不自行执行编译命令):用 TransPyV.exe 重跑
--project ./Test/FakeDuckTest/project.json --clean --clear-cache --rebuild-includes --traceback
预期 115 行不再报错;若仍在 parts2.get(0)(131 行)等处冒新错,请把栈贴回来。