fix(tpc): 注解侧泛型基名方向判定,阻止裸泛型 RHS 覆盖已特化注解类型
HandleAnnAssign 原无条件以 RHS.pointee 重建 alloca,会把注解已解析出的 Base[...] 特化类型覆盖成裸泛型基类,导致后续 .get() 按错误元素类型分派(list[int].get 返回 i32)后 inttoptr 截断。新增注解侧泛型基名结构性识别,仅拦此方向错误。
This commit is contained in:
1 parent
5680592f37
commit
0ffaadc95e
1 file changed
+41
-2
@@ -747,6 +747,27 @@ class AnnAssignHandle(BaseHandle):
|
||||
Gen.global_struct_class[VarName] = Node.annotation.id
|
||||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||||
return
|
||||
# 方向判定用:取注解一侧的泛型基名(`Base[...]` 或 `Base[...] | t.CPtr`
|
||||
# 形态中的 Base)。此判据**不依赖泛型模板注册表**(list/dict 等内建
|
||||
# 容器可能未登记),只做结构性识别;仅 Name 形态可识别,属性链
|
||||
# (如 t.CPtr[...])不参与。
|
||||
_ann_gen_base: str | None = None
|
||||
_ann_sub_side: ast.expr | None = None
|
||||
if isinstance(Node.annotation, ast.Subscript):
|
||||
_ann_sub_side = Node.annotation
|
||||
elif (isinstance(Node.annotation, ast.BinOp)
|
||||
and isinstance(Node.annotation.op, ast.BitOr)):
|
||||
for _ann_side in (Node.annotation.left, Node.annotation.right):
|
||||
if isinstance(_ann_side, ast.Subscript):
|
||||
_ann_sub_side = _ann_side
|
||||
break
|
||||
if _ann_sub_side is not None:
|
||||
_ann_base_v: ast.expr = _ann_sub_side.value
|
||||
# 兼容嵌套下标链(Base[...][...]):逐层剥到最内层 Name
|
||||
while isinstance(_ann_base_v, ast.Subscript):
|
||||
_ann_base_v = _ann_base_v.value
|
||||
if isinstance(_ann_base_v, ast.Name):
|
||||
_ann_gen_base = _ann_base_v.id
|
||||
for CN, ST in Gen.structs.items():
|
||||
# 泛型占位类型(T/U/V,如 GSList[T].Head 的元素类型)opaque 无 body,
|
||||
# 不参与变量类型重建/var_struct_class 设置:跟随 T* 会污染注解声明的
|
||||
@@ -782,8 +803,26 @@ class AnnAssignHandle(BaseHandle):
|
||||
Gen.var_struct_class[VarName] = resolved_cn
|
||||
Gen.global_struct_class[VarName] = resolved_cn
|
||||
if isinstance(VarType, ir.PointerType) and VarType.pointee is not ST and VarType.pointee != ST:
|
||||
var = Gen._allocaEntry(ir.PointerType(pointee), name=VarName)
|
||||
VarType = ir.PointerType(pointee)
|
||||
# 方向判定:本重建的本意是「注解退化成裸基类 / i8*,
|
||||
# RHS 构造出精确特化 ⇒ 用 RHS 反向升级」(见 L765 注释)。
|
||||
# 但 RHS 的 pointee 若为**裸泛型基类**(丢类型实参,如
|
||||
# {sha1}.list)而注解一侧本身就是带类型实参的泛型
|
||||
# (`Base[...]` 或 `Base[...] | t.CPtr`),以 RHS 重建
|
||||
# alloca 会把注解已解析出的特化类型覆盖成裸基类 → 之后
|
||||
# .get() 按错误元素类型分派(list[int].get 返回 i32)→
|
||||
# inttoptr 截断指针 → 读垃圾 AST 节点崩溃
|
||||
# (MatchGenMixin._handle_renum_match 现场根因)。
|
||||
# 判据(_cn_short 无 '[' 且与注解泛型基名同名)只拦这一
|
||||
# 确定的方向错误,属**结构性识别**而非兜底:注解退化为
|
||||
# i8*/裸基类、RHS 精确特化的合法升级路径不受影响。
|
||||
_rb_is_bare_generic: bool = (
|
||||
_ann_gen_base is not None
|
||||
and '[' not in _cn_short
|
||||
and _cn_short == _ann_gen_base
|
||||
)
|
||||
if not _rb_is_bare_generic:
|
||||
var = Gen._allocaEntry(ir.PointerType(pointee), name=VarName)
|
||||
VarType = ir.PointerType(pointee)
|
||||
break
|
||||
if InitValue:
|
||||
try:
|
||||
|
||||
Reference in new issue
Block a user