diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 56f1276..8b88f77 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -1446,11 +1446,15 @@ novirtual class AssignGenMixin: # Double-pointer arithmetic: delegate the check to ExprGenOps.fail_if_double_ptr_binop self.Gen.ExprGenOps.fail_if_double_ptr_binop(pool, op, lhs, rhs, node, 1) - # x op= y 的操作数约束(fail-fast,先于运算与提升): - # ① y 的有效宽度必须 <= x 的宽度。变量按其 LLVM 类型宽度;常量按其值的**最小可存宽度** - # (所以 `u8 += 1` 合法、`u8 += 300` 报错)。y 更宽 = 隐式收窄,必须先显式收窄再写。 - # ② 不允许 y 显式有符号而 x 无符号:负值经符号扩展会变成巨大的无符号值,属静默语义改变。 - # 移位(<<= / >>=)**豁免** ①②:计数不是写回目标的值,改用静态范围检查(见下方)。 + # x op= y 的操作数宽度约束(fail-fast,先于运算与提升): + # y 的有效宽度必须 <= x 的宽度。变量按其 LLVM 类型宽度;常量按其值的**最小可存宽度** + # (所以 `u8 += 1` 合法、`u8 += 300` 报错)。y 更宽 = 隐式收窄,必须先显式收窄再写。 + # 移位(<<= / >>=)**豁免**:计数不是写回目标的值,改用静态范围检查(见下方)。 + # + # 说明:右值有符号而左值无符号**不再单独拦截**——拓宽方向已由 sext/zext 规则统一决定 + # (i 类 sext、u 类 zext,见 wiki/Implicit.md §1.1),且二元形态 `x = x op y` 本就允许 + # (如 `sizet += int` 里 int 先拓宽到 u64 再相加)。两条路径口径必须一致,否则同一语义 + # 换个写法就报错。 y_node_aa: ast.AST* = None if node is not None and node.kind() == ast.ASTKind.AugAssign: y_node_aa = ast.AugAssign*(node).value if lhs_bits != 0 and rhs_bits != 0 and op != ast.OpKind.LShift and op != ast.OpKind.RShift: @@ -1460,12 +1464,6 @@ novirtual class AssignGenMixin: if cn_aa.const_kind == ast.CONST_INT: y_bits_eff = self.define_min_width(cn_aa.int_val) if y_bits_eff > lhs_bits: self.Gen.TypeGenErr.fatal_error(node, f"[VPC] augmented assignment operand too wide: the right-hand side needs {y_bits_eff} bits, " f"but the target provides only {lhs_bits} bits; an implicit narrowing is forbidden. " f"Fix: narrow the right-hand side explicitly (e.g. uint{lhs_bits}(...) / int{lhs_bits}(...)) before the operation.", "CastError") - x_uns_aa: int = 0 - if lhs_node is not None: x_uns_aa = self.Gen.ExprGenOps._node_type_unsigned(pool, lhs_node, trans) - y_sgn_aa: int = 0 - if y_node_aa is not None: y_sgn_aa = self.Gen.ExprGenOps._node_type_signed(pool, y_node_aa, trans) - if x_uns_aa != 0 and y_sgn_aa != 0: - self.Gen.TypeGenErr.fatal_error(node, "[VPC] augmented assignment operand signedness conflict: the right-hand side is explicitly signed " "while the target is unsigned; sign extension would turn negative values into huge unsigned values. " "Fix: use an unsigned right-hand side (e.g. uint32(...)), or make the target signed.", "CastError") # Integer op: type promotion if lhs_bits > rhs_bits and rhs_bits > 0: rhs = self.Gen.ExprGenBase.coerce_to_type(builder, rhs, lhs.Ty, node, trans)