From 8263f6ec47a33838eacbff78c8aff9957a390aac Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 29 Sep 2026 12:09:12 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpc):=20=E5=BD=A2=E5=8F=82=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3=E8=A7=A3=E6=9E=90=E8=90=BD=E5=88=B0=20i32=20=E6=97=B6?= =?UTF-8?q?=20fail-fast=EF=BC=88=E4=B8=8B=E6=A0=87/=E8=81=94=E5=90=88?= =?UTF-8?q?=E5=BD=A2=E6=80=81=E4=B8=8D=E5=8F=AF=E8=83=BD=E6=98=AF=20i32?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- lib/core/LLVMTypeMapper.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/core/LLVMTypeMapper.py b/lib/core/LLVMTypeMapper.py index f5750a6..4243b10 100644 --- a/lib/core/LLVMTypeMapper.py +++ b/lib/core/LLVMTypeMapper.py @@ -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 类型字符串"""