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.global_struct_class[VarName] = Node.annotation.id
|
||||||
Gen._record_var_signedness(VarName, IsUnsigned)
|
Gen._record_var_signedness(VarName, IsUnsigned)
|
||||||
return
|
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():
|
for CN, ST in Gen.structs.items():
|
||||||
# 泛型占位类型(T/U/V,如 GSList[T].Head 的元素类型)opaque 无 body,
|
# 泛型占位类型(T/U/V,如 GSList[T].Head 的元素类型)opaque 无 body,
|
||||||
# 不参与变量类型重建/var_struct_class 设置:跟随 T* 会污染注解声明的
|
# 不参与变量类型重建/var_struct_class 设置:跟随 T* 会污染注解声明的
|
||||||
@@ -782,8 +803,26 @@ class AnnAssignHandle(BaseHandle):
|
|||||||
Gen.var_struct_class[VarName] = resolved_cn
|
Gen.var_struct_class[VarName] = resolved_cn
|
||||||
Gen.global_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:
|
if isinstance(VarType, ir.PointerType) and VarType.pointee is not ST and VarType.pointee != ST:
|
||||||
var = Gen._allocaEntry(ir.PointerType(pointee), name=VarName)
|
# 方向判定:本重建的本意是「注解退化成裸基类 / i8*,
|
||||||
VarType = ir.PointerType(pointee)
|
# 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
|
break
|
||||||
if InitValue:
|
if InitValue:
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in new issue
Block a user