fix(tpc): 形参注解解析落到 i32 时 fail-fast(下标/联合形态不可能是 i32)

a 编译器缺陷(无兜底铁律)。根因链:stub 与 .vpi 两侧都写着
`type_args: list[str] | t.CPtr`(等价 `list[str]*`),**都对**;错在消费侧:
`LLVMTypeMapper._resolve_subscript` 对**单参泛型下标**(`list[str]`,非 `list[T, N]`
定长数组)没有分支,落到末尾 `回退到 i32` 的兜底 —— 该串经
SymbolTypeResolver → SymbolTable._InsertFuncSymbol 原样存进 `FuncPtrParams`,
再由 BuildLLVMFuncTypeFromSig 物化成**形参 i32**,于是调用点报
「实参 %"650c1c3366d09e39.list[str]"* 不能隐式转为整数参数 i32」,把真因
(注解没解析出来)掩盖成"调用点类型不匹配"。

改法:`get_func_param_type_str` 末尾加守卫 —— 注解是 Subscript / 联合(BinOp|)而
解析结果恰为 `'i32'` 时 fail-fast,并带上注解原文(由 SymbolTypeResolver 再补函数名/
形参序号与名字)。理由:下标形态的合法结果是容器/泛型/定长数组(指针、数组或结构体
指针),联合形态是 `T | t.CPtr` 的指针叠加 —— 都不会是 i32;只有"解析失败"才会是。

现场:CallGenMixin.vp:149 → `_specialize_generic_class(trans, gen_class_name, gen_type_args)`
      callee=2292045c9694100e.ClassGenGeneric._specialize_generic_class
      逐项 [3] arg=%"650c1c3366d09e39.list[str]"* param=i32
This commit is contained in:
TermiNexus committed 2026-09-29 12:09:12 +08:00
1 parent 7167703ca7
commit 8263f6ec47
1 file changed
+27 -4
+27 -4
View File
@@ -141,14 +141,37 @@ class LLVMTypeMapper:
return result if result else 'i32'
def get_func_param_type_str(self, annotation_node: ast.AST | None) -> str:
"""提取函数参数类型的 LLVM 字符串"""
"""提取函数参数类型的 LLVM 字符串。
末尾的「不许静默变 i32」守卫:`Subscript` / 联合(`|`)形态的形参注解若解析结果
是 `'i32'`,只可能是**解析失败后的兜底** —— 合法的下标注解是容器 / 泛型 / 定长数组
(解析出指针、数组或结构体指针),合法的联合写法是 `T | t.CPtr` 这类指针叠加,都
不会是 i32。该串会被 `_InsertFuncSymbol` 原样存进符号表(`FuncPtrParams`),再由
`BuildLLVMFuncTypeFromSig` 物化成形参类型 —— 一旦是 i32,调用点就在 `_adjust_args`
报「实参 %X* 不能隐式转为 i32」,把真因(**注解没解析出来**)掩盖成"调用点类型
不匹配"(现场:CallGenMixin.vp:149 调用 `_specialize_generic_class` 的
`type_args: list[str]*`)。故此处响亮失败,并带上注解原文。
"""
if annotation_node is None:
return 'i8*'
result: str
if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr):
# 统一走 CPtr 感知的联合解析
return self._resolve_bitor(annotation_node)
result: str = self.get_llvm_type_str(annotation_node)
return result if result else 'i8*'
result = self._resolve_bitor(annotation_node)
else:
result = self.get_llvm_type_str(annotation_node)
if not result:
result = 'i8*'
if result == 'i32' and isinstance(annotation_node, (ast.Subscript, ast.BinOp)):
_text: str
try:
_text = ast.unparse(annotation_node)
except Exception:
_text = f'<{type(annotation_node).__name__}>'
raise TypeNameUnresolvedError(
f"形参注解 '{_text}' 解析失败并落到 i32(下标 / 联合形态的合法结果应为"
f"指针、数组或结构体指针,不会是 i32)—— 拒绝静默降级为 i32")
return result
def resolve_typedef_value_type(self, node: ast.AST | None) -> str:
"""解析 typedef 值表达式的 C 类型字符串"""