From 85d68e591388852bed13b93c9b20e396b1d33817 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 1 Oct 2026 21:53:43 +0800 Subject: [PATCH] =?UTF-8?q?fix(type):=20=E6=94=AF=E6=8C=81=E5=86=85?= =?UTF-8?q?=E5=BB=BA=E8=A3=B8=E5=90=8D=E5=87=BD=E6=95=B0=E6=8C=87=E9=92=88?= =?UTF-8?q?=E6=9E=84=E9=80=A0=E5=AD=90=20callable[[...],=20R]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TransPyV 侧 TypeGenResolve._IsCallableSubscriptValue 已把 t.Callable[...] 与内建裸名 callable[...] / Callable[...] 视为逐点等价,TPC 侧只有模块限定形态能识别: - TypeAnnotationResolver._from_node_subscript 的 Callable 分支要求 IsTModule(parts[0]), 裸名落进泛型特化兜底未命中 → 空 CTypeInfo;改为裸名同判并共用同一构造体。 - DeclarationGenerator._get_type_str 的 Subscript 分支缺 callable 判定,落到末尾 兜底 'i32';补判返回 'i8*'(与 Attribute 分支的 t.Callable 一致)。 现场:Repl.vp:307 ReplFragFn: callable[[rawptr], int] 被声明成 i32 全局, Repl.vp:2727 ReplFragFn = fp_addr(i8*)触发「指针隐式转整数已禁止」。 --- lib/Projectrans/DeclarationGenerator.py | 6 ++++++ lib/core/TypeAnnotationResolver.py | 18 +++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/Projectrans/DeclarationGenerator.py b/lib/Projectrans/DeclarationGenerator.py index d340f8c..842d1a9 100644 --- a/lib/Projectrans/DeclarationGenerator.py +++ b/lib/Projectrans/DeclarationGenerator.py @@ -1377,6 +1377,12 @@ class DeclarationGenerator: if (IsPtrSubscriptNode(annotation, TCAliasMap=self._t_c_imported_names) or (ValueIsCPtr and isinstance(annotation.slice, (ast.Attribute, ast.Name, ast.Subscript)))): return self._ptr_subscript_type_str(annotation) + # 内建裸名函数指针构造子 callable[...] / Callable[...]:与 Attribute 分支的 + # t.Callable[...] 逐点等价(同为 i8*)。缺此分支时落到下方 Name 泛型特化 / + # 兜底返回 'i32'(现场 Repl.vp:307 `ReplFragFn: callable[[rawptr], int]` + # 声明成 i32 全局 ⇒ 赋 i8* 触发「指针隐式转整数」)。 + if isinstance(annotation.value, ast.Name) and (annotation.value.id == 'callable' or annotation.value.id == 'Callable'): + return 'i8*' base: str = self._get_type_str(annotation.value) if base == 'i8*' and isinstance(annotation.slice, ast.Constant): return f'[{self._get_const_int(annotation.slice)} x i8]' diff --git a/lib/core/TypeAnnotationResolver.py b/lib/core/TypeAnnotationResolver.py index ad4e734..bb405cc 100644 --- a/lib/core/TypeAnnotationResolver.py +++ b/lib/core/TypeAnnotationResolver.py @@ -954,15 +954,27 @@ class TypeAnnotationResolver: if ElemInfo.IsPtr and not ElemInfo.ArrayDims: Result.PtrCount = max(Result.PtrCount, 1) return Result + # 函数指针构造子的两种书写形态逐点等价(对齐 TPV + # TypeGenResolve._IsCallableSubscriptValue): + # t.Callable[...] / c.Callable[...] → 模块限定 Attribute + # callable[...] / Callable[...] → 内建裸名(无需 import) + # 裸名形态此前落进下方泛型特化兜底(ResolveGenericClassSpecName)未命中 ⇒ + # 空 CTypeInfo ⇒ 槽位类型退化 i32(现场 Repl.vp:307 + # `ReplFragFn: callable[[rawptr], int]`,赋 i8* 时被「指针隐式转整数」拦下)。 + parts: list[str] = [] + IsBareCallable: bool = False if isinstance(base, ast.Attribute): - parts: list[str] = [] current: ast.AST = base while isinstance(current, ast.Attribute): parts.insert(0, current.attr) current = current.value if isinstance(current, ast.Name): parts.insert(0, current.id) - if parts and IsTModule(parts[0], SymbolTable) and parts[-1] == t.CPtr.__name__: + elif isinstance(base, ast.Name) and (base.id == 'callable' or base.id == 'Callable'): + # 裸名只在注解位置当函数指针构造子(非类型位置仍是普通标识符) + IsBareCallable = True + if isinstance(base, ast.Attribute) or IsBareCallable: + if (not IsBareCallable) and parts and IsTModule(parts[0], SymbolTable) and parts[-1] == t.CPtr.__name__: Result: CTypeInfo = CTypeInfo() Result.BaseType = t.CVoid() Result.PtrCount = 1 @@ -990,7 +1002,7 @@ class TypeAnnotationResolver: if SliceInfo and SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid): Result.BaseType = SliceInfo.BaseType return Result - if parts and IsTModule(parts[0], SymbolTable) and parts[-1] == 'Callable': + if IsBareCallable or (parts and IsTModule(parts[0], SymbolTable) and parts[-1] == 'Callable'): Result = CTypeInfo() Result.IsFuncPtr = True slice_node = Node.slice