fix(gen/assign): 模块级与 nonlocal 分支补写赋值注解上下文通道
模块级 AnnAssign 的 mod_glob 分支与 global 语句分支、以及 nonlocal 分支此前均未写入 trans.CurAssignAnnot/CurAssignNode,导致模块级/闭包内 s: Stack[int] = Stack() 在泛型裸名构造处 fail-fast、x: int = c.Deref(p) 退化为 i8 单字节读取 按主分支既有先例(AssignGenMixin set 在 RHS 翻译前 / clear 在返回前)在三处分支补齐同款 set/clear,并覆盖全部分支的提前 return 与末尾出口,避免通道残留污染后续 c.Deref 读取宽度与泛型构造类型实参推断 影响面: 全仓 模块级/global/nonlocal 的 X: T = c.Deref(...) 与 X: Generic[...] = Ctor(...) 均 0 处,属纯增量
This commit is contained in:
1 parent
5a59432733
commit
617d4ea911
1 file changed
+57
@@ -1487,6 +1487,14 @@ class AssignGenMixin:
|
||||
aa_glob_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if mod_alloca.Ty is not None:
|
||||
aa_glob_ty = mod_alloca.Ty.Pointee
|
||||
# 供 c.Deref(i8*) 推断读取宽度 / 裸名泛型构造从注解推断类型实参:
|
||||
# 与主分支(普通局部变量路径)同一口径——必须在翻译 RHS 之前写入
|
||||
# CurAssignAnnot/CurAssignNode。四处(主分支 / 本 global 分支 /
|
||||
# 下方 mod_glob 分支 / 下方 nonlocal 分支)必须同步,否则
|
||||
# `x: int = c.Deref(p)` 的读取宽度与 `s: Stack[int] = Stack()`
|
||||
# 的类型实参推断都会拿不到注解。
|
||||
trans.CurAssignAnnot = aa.annotation
|
||||
trans.CurAssignNode = aa.value
|
||||
rhs_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, aa.value,
|
||||
None, 0, trans, aa_glob_ty)
|
||||
@@ -1515,6 +1523,10 @@ class AssignGenMixin:
|
||||
builder, stg_ty_aa, rhs_val)
|
||||
if stg_obj_val_aa is not None:
|
||||
llvmlite.build_store(builder, stg_obj_val_aa, stg_ref_aa)
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款——
|
||||
# 提前 return 前必须清,否则泄漏到后续语句
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
target_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if mod_alloca.Ty is not None:
|
||||
@@ -1522,6 +1534,12 @@ class AssignGenMixin:
|
||||
if target_ty is not None:
|
||||
rhs_val = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val, target_ty, node, trans)
|
||||
llvmlite.build_store(builder, rhs_val, mod_alloca)
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款。四处(主分支 /
|
||||
# 本 global 分支 / 下方 mod_glob 分支 / 下方 nonlocal 分支)必须同步清除,
|
||||
# 否则残留注解会让后续 while 条件/比较等处的 c.Deref 被误判读取宽度
|
||||
# (i8* 按 i32* 读 4 字节),也会污染裸名泛型构造的类型实参推断
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
|
||||
# nonlocal 变量:通过闭包 env 写入
|
||||
@@ -1537,6 +1555,14 @@ class AssignGenMixin:
|
||||
nl_target_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if nl_ptr is not None and nl_ptr.Ty is not None:
|
||||
nl_target_ty = nl_ptr.Ty.Pointee
|
||||
# 供 c.Deref(i8*) 推断读取宽度 / 裸名泛型构造从注解推断类型实参:
|
||||
# 与主分支、上方 global 分支、下方 mod_glob 分支同一口径——必须在
|
||||
# 翻译 RHS 之前写入 CurAssignAnnot/CurAssignNode。四处(主分支 /
|
||||
# global / mod_glob / 本 nonlocal 分支)必须同步,否则
|
||||
# `nonlocal x: int = c.Deref(p)` 的读取宽度与
|
||||
# `nonlocal s: Stack[int] = Stack()` 的类型实参推断都会拿不到注解。
|
||||
trans.CurAssignAnnot = aa.annotation
|
||||
trans.CurAssignNode = aa.value
|
||||
rhs_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, aa.value,
|
||||
None, 0, trans, nl_target_ty)
|
||||
@@ -1547,10 +1573,20 @@ class AssignGenMixin:
|
||||
VLogger.error(
|
||||
f"nonlocal 变量类型信息丢失,无法写入: {nm.id}",
|
||||
"HandlesAnnAssign")
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款——
|
||||
# 提前 return 前必须清,否则泄漏到后续语句
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
rhs_coerced: llvmlite.Value | t.CPtr = self.Gen.ExprGenBase.coerce_to_type(
|
||||
builder, rhs_val, nl_target_ty, node)
|
||||
llvmlite.build_store(builder, rhs_coerced, nl_ptr)
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款。四处(主分支 /
|
||||
# global / mod_glob / 本 nonlocal 分支)必须同步清除,否则残留注解会让
|
||||
# 后续 while 条件/比较等处的 c.Deref 被误判读取宽度(i8* 按 i32* 读 4
|
||||
# 字节),也会污染裸名泛型构造的类型实参推断
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
|
||||
# 模块级全局变量(由 handle_module_level_var 注册到模块作用域)
|
||||
@@ -1572,6 +1608,13 @@ class AssignGenMixin:
|
||||
mg_val_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if mod_glob.Ty is not None:
|
||||
mg_val_ty = mod_glob.Ty.Pointee
|
||||
# 供 c.Deref(i8*) 推断读取宽度 / 裸名泛型构造从注解推断类型实参:
|
||||
# 与主分支、上方 global 分支同一口径——翻译 RHS 前写入
|
||||
# CurAssignAnnot/CurAssignNode。模块级 `s: Stack[int] = Stack()`
|
||||
# 走的就是本分支,四处(主分支 / global / 本 mod_glob 分支 /
|
||||
# 上方 nonlocal 分支)必须同步。
|
||||
trans.CurAssignAnnot = aa.annotation
|
||||
trans.CurAssignNode = aa.value
|
||||
rhs_val_mg: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
|
||||
builder, pool, mod, aa.value,
|
||||
None, 0, trans, mg_val_ty)
|
||||
@@ -1600,6 +1643,10 @@ class AssignGenMixin:
|
||||
builder, stg_ty_mg, rhs_val_mg)
|
||||
if stg_obj_val_mg is not None:
|
||||
llvmlite.build_store(builder, stg_obj_val_mg, stg_ref_mg)
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款,
|
||||
# 提前 return 前必须清,否则泄漏到后续语句
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
target_ty_mg: llvmlite.LLVMType | t.CPtr = None
|
||||
if mod_glob.Ty is not None:
|
||||
@@ -1607,6 +1654,12 @@ class AssignGenMixin:
|
||||
if target_ty_mg is not None:
|
||||
rhs_val_mg = self.Gen.ExprGenBase.coerce_to_type(builder, rhs_val_mg, target_ty_mg, node)
|
||||
llvmlite.build_store(builder, rhs_val_mg, mod_glob)
|
||||
# 清除赋值上下文(防残留):与主分支清空时机同款。四处(主分支 /
|
||||
# 上方 global 分支 / 本 mod_glob 分支 / 上方 nonlocal 分支)必须同步清除,
|
||||
# 否则残留注解会让后续语句的 c.Deref 被误判读取宽度,并污染裸名泛型
|
||||
# 构造的类型实参推断
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
return 0
|
||||
|
||||
# 单参 t.CArray[elem_ty] + 列表字面量 → 按静态数组处理(count 从字面量长度推断)
|
||||
@@ -1757,6 +1810,9 @@ class AssignGenMixin:
|
||||
# 供 c.Deref(i8*) 推断读取宽度:v: int = c.Deref(p) → 读 i32
|
||||
# CurAssignNode 记录 RHS 节点:translate_c_deref 据此判定 Deref
|
||||
# 是否为赋值直接 RHS(对齐 TPC _infer_deref_target_type)。
|
||||
# 注意:本主分支(普通局部变量)、上方 global 分支、mod_glob 分支、
|
||||
# nonlocal 分支四处的 set/clear 必须同步(模块级 AnnAssign 走
|
||||
# mod_glob;闭包内 AnnAssign 走 nonlocal)。
|
||||
trans.CurAssignAnnot = aa.annotation
|
||||
trans.CurAssignNode = aa.value
|
||||
# P1-A:局部变量 alloca 的 pointee 类型作为 target_ty(同全局分支),
|
||||
@@ -1878,6 +1934,7 @@ class AssignGenMixin:
|
||||
# 清除赋值上下文(防残留):CurAssignAnnot/CurAssignNode 只在该
|
||||
# AnnAssign 的 RHS 翻译期间有效,否则后续 while 条件/比较等处的
|
||||
# c.Deref 会被残留注解误判读取宽度(i8* 被 bitcast i32* 读 4 字节)。
|
||||
# 四处(本主分支 / global / mod_glob / nonlocal)必须同步清除。
|
||||
trans.CurAssignAnnot = None
|
||||
trans.CurAssignNode = None
|
||||
|
||||
|
||||
Reference in new issue
Block a user