fix(VpiReader): 返回/形参注解切分只在顶层 | 处断段(括号感知)

_resolve_vpi_ret_annot_str 原按裸 `|` 切段,`list[ast.AST | t.CPtr] | t.CPtr` 会被切成
`list[ast.AST` / `t.CPtr]` / `t.CPtr`;首段再经 strrchr('.') 落到 `AST` ⇒ 定义侧类型解析成
`AST*`(元素指针),而正确答案是 list 专化结构体的指针。现场:跨模块调用 coerce 时报
"源类型 list[AST*]* → 目标类型 AST*"(CallGenLib._coerce_args_to_def_params 的 cargs 形参)。

现切分按 `[`/`]` 深度,只在顶层 `|` 处断段(与 _cache_vpi_param_annots_text 的顶层逗号
切分同口径)。改后该段解析不出 ⇒ 落 i8* 通配,与 `list[str] | t.CPtr` 等同形注解的既有
行为一致;配合 CallGen 侧的 bitcast 对齐(见上一笔)即可安全使用。
This commit is contained in:
TermiNexus committed 2026-10-01 20:45:21 +08:00
1 parent 8e3811c490
commit a714ec9d37
1 file changed
+16 -1
+16 -1
View File
@@ -1526,7 +1526,22 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*,
while pos < buf_len and ret_annot[pos] == ' ':
pos += 1
seg_start: sizet = pos
while pos < buf_len and ret_annot[pos] != '|':
# 只在**顶层**切 `|`:`[...]` 内的 `|` 属于泛型实参内部的联合注解,裸切会把首段
# 截成 `list[ast.AST`(来自 `list[ast.AST | t.CPtr] | t.CPtr`),该段再经
# strrchr('.') 落到 `AST` ⇒ 定义侧解析成 `AST*`(元素的指针),而正确答案是
# list 专化结构的指针(至少也应落 i8* 通配)。深度计数按 `[`/`]`,与
# _cache_vpi_param_annots_text 的顶层逗号切分同口径。
depth_ra: int = 0
while pos < buf_len:
ch_ra: char = ret_annot[pos]
if ch_ra == '[':
depth_ra += 1
elif ch_ra == ']':
if depth_ra > 0:
depth_ra -= 1
elif ch_ra == '|':
if depth_ra == 0:
break
pos += 1
seg_end: sizet = pos
# trim 尾随空格