fix(declgen): 联合中 t.CPtr[T] 下标段按 Ptr^N 叠加,与 LLVMTypeMapper 口径对齐

_get_type_str 的 BinOp 段原先在右段非 i8* 时落到 星号在左值则直接返回左值 的启发式,左值已是指针(BYTEPTR=>i8*)时会吞掉右段层数(BYTEPTR | t.CPtr[t.CPtr] 得 i8*,Mapper 得 i8***,同份 stub 自相矛盾)

新增 t.CPtr[T] 分支(两侧对称,置于该启发式之前),复用文件内既有 _ptr_level_of 取层数并按定义侧 TypeGenResolve 口径改为纯外包 N 层(去掉原 struct 吸收半截语义);LLVM 聚合左值显式排除。A/B 实测 135 个 .pyi 输出逐字节相同,现有语料零影响
This commit is contained in:
TermiNexus committed 2026-09-16 07:11:23 +08:00
1 parent 2427a6e992
commit 8d950f5d43
1 file changed
+28 -1
+28 -1
View File
@@ -8,7 +8,7 @@ import llvmlite.ir as ir
from lib.includes import t
from lib.includes.t import CTypeRegistry
from lib.core.SymbolUtils import IsListAnnotation, AnnotationContainsName
from lib.core.SymbolUtils import IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode
class DeclarationGenerator:
@@ -1019,6 +1019,23 @@ class DeclarationGenerator:
# 其他未知类型保守估算
return 8
@staticmethod
def _ptr_level_of(type_str: str) -> int:
"""统计类型字符串尾部的指针层数('i8***' → 3,'i32' → 0)"""
return len(type_str) - len(type_str.rstrip('*'))
def _merge_cptr_subscript(self, base_type: str, cptr_sub_type: str) -> str:
"""base | t.CPtr[T] → Ptr^N(base_type),N = t.CPtr[T] 段自身指针层数。
与定义侧 TPV TypeGenResolve.vp:2610-2639 同口径:数 CPtr 侧已解析类型的
外层 Ptr 嵌套层 N(TypeGenResolve.vp:2616-2632),再给另一侧**纯外包**
N 层 Ptr(TypeGenResolve.vp:2633-2639,对 struct 基类型亦不吸收)。
与 LLVMTypeMapper._resolve_bitor 的 IsCPtrSubscriptNode 分支(_add_pointer_levels
逐层追加)同口径,对同一批形态两处结果一致。
注:裸 | t.CPtr(非下标标记)仍走上方的 %"..."* 吸收分支,与本节无关。
"""
return base_type + '*' * self._ptr_level_of(cptr_sub_type)
def _get_type_str(self, annotation: ast.AST | None, embedded: bool = False) -> str:
if annotation is None:
return 'i8*'
@@ -1158,6 +1175,16 @@ class DeclarationGenerator:
if '*' in left_type:
return f'{left_type}*'
return f'{left_type}*'
# X | t.CPtr[T](T 为下标段,非裸标记):CPtr 侧贡献自身指针层数 N,
# 另一侧外包 N 层(Ptr^N(X));左右两侧写法对称(定义侧 TPV
# TypeGenResolve.vp:2604-2609 亦两侧皆判)。必须先于下方
# "'*' in left_type → 直接返回左值":否则左值本身已是指针
# (BYTEPTR⇒i8*)时会吞掉右段层数(BYTEPTR | t.CPtr[t.CPtr] 改前得 i8*)。
# LLVM 聚合([N x T] / { ... })不可再外包指针层,保持既有行为(只报不改)。
if IsCPtrSubscriptNode(annotation.right) and left_type[:1] not in ('[', '{'):
return self._merge_cptr_subscript(left_type, right_type)
if IsCPtrSubscriptNode(annotation.left) and right_type[:1] not in ('[', '{'):
return self._merge_cptr_subscript(right_type, left_type)
if '*' in left_type:
return left_type
if '*' in right_type: