fix(gentype): list[t.CPtr] 特化与 list[对象] elem_size 根本修复

两处根因:
1. list[t.CPtr] 报 Undefined method 'append':
   - _resolve_generic_slice_type 对 t.CPtr 返回裸名 'CPtr',type_map['T']='CPtr'
     替换进模板(item: CPtr)后 CPtr 不在顶层作用域 → append 声明注册失败
   - 改保留带前缀 't.CPtr'(可解析)
   - 查找端(SymbolUtils.FindStructNameInAnnotation)与声明端
     (DeclarationGenerator)的 CPtr 统一规范化为 'ptr',与特化端
     _mangle_generic_class_name 一致(list[CPtr]/list[i8*] vs list[ptr])
   - _specialize_generic_class 的 cptr_params/class_type_names 判定改 tn_bare
2. list[对象] elem_size=0(get(0)==get(1) 同槽根因):
   - T.__sizeof__() 特化后为 'X | t.CPtr'(BinOp 联合),_HandleSizeofLlvm
     对 BinOp 落到 else 返回 0 → list.__elem_size__=0 → 元素全写同槽
   - 改含 t.CPtr 的联合类型返回 8(指针大小)
This commit is contained in:
TermiNexus committed 2026-08-19 22:44:15 +08:00
1 parent e82640ac94
commit 2f0d52e736
5 files changed
+97 -23

No files matched your search

+35 -16
View File
@@ -26,6 +26,15 @@ def _safe_ptr_type(ty: ir.Type) -> ir.Type:
return ty
def _BinOpContainsCPtr(node: ast.AST) -> bool:
"""递归检查 BinOp(BitOr) 联合类型中是否含 t.CPtr(指针标记)"""
if isinstance(node, ast.Attribute):
return node.attr == 'CPtr'
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
return _BinOpContainsCPtr(node.left) or _BinOpContainsCPtr(node.right)
return False
class ExprCallHandle(BaseHandle):
# vtable on-demand 缓存(类级,跨 worker 任务共享,进程内单线程无竞争)。
# 原实现 pyi_cache 是 _try_register_vtable_ondemand 函数局部变量,每次调用都
@@ -2457,22 +2466,23 @@ class ExprCallHandle(BaseHandle):
if idx is None or idx >= len(st.elements):
return None
# ============================================================
# 修复(2026-08-13):class_members 与 struct.elements 数量不一致时对齐。
# 根因链(NewAstTest ASTCtx 枚举丢失):
# DeclarationGenerator/收集路径生成的 class_members 可能漏部分 Mixin/自动
# 字段(如 Generator 漏 GenericSpecDepth/GenericClassFiles/ISINSTANCE_CLASS_MAX
# 3 个,class_members=88 vs struct=91),导致 this_adjust 用 class_members
# 索引算错字节偏移(Generator 624 vs 真实 644)。StmtGenMixin 方法(find_enum/
# register_enum/is_enum_class)字段访问错位 20 字节 → EnumTable 落在
# ReexportSrcs 内存 → 与 reexport 数据冲突覆盖 → ASTCtx 等枚举丢失。
# 修正:字段真实 struct 索引 = class_members 索引 + (struct 元素数 - members 数)。
# 前提:遗漏字段位于目标字段之前(本 bug 场景成立:漏字段在 StmtGenMixin 前)。
# diff_elems 修正(2026-08-13):class_members 与 struct.elements 数量
# 不一致时对齐(前提:遗漏字段位于目标字段之前)。
# ============================================================
diff_elems: int = len(st.elements) - len(members)
if diff_elems > 0:
idx += diff_elems
if idx >= len(st.elements):
return None
# 临时诊断(2026-08-18,确定后移除):捕获 this_adjust 计算输入,
# 定位 TPC 并行 worker 间 class_members/struct 不一致导致的偏移抖动。
if lookup_cls in ('Generator',):
try:
with open(r'd:\Users\TermiNexus\Desktop\TransPyC\_diag_offset.log', 'a', encoding='utf-8') as _f:
_f.write(f"{lookup_cls}|{field_name}|members={len(members)}|struct={len(st.elements)}"
f"|vtable={int(has_vtable)}|idx={idx}|diff={diff_elems}\n")
except Exception:
pass
offset: int = 0
for i in range(idx):
et = st.elements[i]
@@ -3513,13 +3523,13 @@ class ExprCallHandle(BaseHandle):
# type_name 保留模块前缀(如 't.CUnsignedChar'),避免 T(0) 替换为
# CUnsignedChar(0) 后因 CUnsignedChar 不在顶层作用域而报
# "Undefined function: 'CUnsignedChar'"。
# t.CPtr 特殊处理:保留 'CPtr' 不带前缀,因为 cptr_params 检测依赖
# _BUILTIN_TYPE_NAMES 中的 'CPtr' 来识别指针类型参数
# t.CPtr 特殊处理:保留 't.CPtr' 带前缀(2026-08-19 根修:此前裸
# 'CPtr' 作为 type_map['T'] 替换进模板(item: T → item: CPtr)时,
# CPtr 不在顶层作用域 → 方法声明注册失败 → "Undefined method
# 'append' in class 'list[CPtr]'"。带前缀 't.CPtr' 可解析。
# 指针参数识别改由 _BUILTIN_TYPE_NAMES 的 tn_bare 检测('t.CPtr'→'CPtr')。
if isinstance(sn, ast.Attribute) and isinstance(sn.value, ast.Name):
if sn.attr == 'CPtr':
raw_name: str = 'CPtr'
else:
raw_name: str = f'{sn.value.id}.{sn.attr}'
raw_name: str = f'{sn.value.id}.{sn.attr}'
else:
raw_name: str = self._get_raw_type_name(sn)
return (type_str, raw_name)
@@ -3608,6 +3618,15 @@ class ExprCallHandle(BaseHandle):
type_name = Node.id
elif isinstance(Node, ast.Attribute):
type_name = Node.attr
elif isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
# 联合类型(如 X | t.CPtr):TPV 注解中 | = and,带 t.CPtr 的联合
# 是指针类型(X* 或 i8*),sizeof = 8(指针大小)。
# list[T].__init__ 的 T.__sizeof__() 特化后 T 被还原为 'X | t.CPtr'
# (_make_replacement_node),此前落到 else 返回 0 → elem_size=0 →
# 所有元素存取同槽(get(0)==get(1),list[对象] join 误报根因)。
if _BinOpContainsCPtr(Node):
return ir.Constant(ir.IntType(64), 8)
return ir.Constant(ir.IntType(64), 0)
else:
return ir.Constant(ir.IntType(64), 0)