From 78fc7313fb59de3a70d9d0a5cef7f6fb64215718 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 27 Sep 2026 08:50:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(gen):=20=E5=90=8C=E5=90=8D=E5=85=A8?= =?UTF-8?q?=E5=B1=80=20+=20=E6=B3=A8=E8=A7=A3=E5=86=B2=E7=AA=81=E4=BC=98?= =?UTF-8?q?=E5=85=88=E6=8A=A5=E9=87=8D=E5=A4=8D=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - translate_annassign: 函数内(无 global/nonlocal、非模块级)再次注解同名变量时,若注解类型与模块级变量类型内容不一致 ⇒ TypeError 重复定义 fail-fast,不再延后到 RHS 的 coerce_to_type 报无关的「指针隐式转整数」(PointerTest/App/main.vp:46 _g_ptr: int = None,全局已是 t.CUInt32T | t.CPtr) - 注解与全局一致时仍按 Python 语义遮蔽为独立局部变量(既有行为不变) - 该检查走 _stg_ty_equal 内容比较(TypePrint),非地址比较,避免 Int32()/Ptr() 新实例造成误判 --- App/lib/core/Gen/AssignGenMixin.vp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 63fef14..a00f13b 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -2127,6 +2127,36 @@ novirtual class AssignGenMixin: f"AnnAssign 缺少类型注解,变量名: {nm.id}", "SyntaxError") + # 重复定义检测(优先于一切下游转换,fail-fast): + # 模块级已有同名变量,而当前作用域既无 global/nonlocal 声明(有则被下方 + # global/nonlocal 分支接管)、又不在模块级(模块级由 handle_module_level_var + # 登记,本就不构成"重复"),此处却用**与全局不一致的注解**再次声明同名变量 + # ⇒ 报重复定义。若无此检查,会先建局部 alloca 再由 RHS 走 coerce_to_type, + # 把根因暴露成无关的 CastError(如 PointerTest/App/main.vp:46 + # `_g_ptr: int = None`:全局已是 t.CUInt32T | t.CPtr,报"指针隐式转整数")。 + # 注解与全局**一致**时不报错:保持 Python 语义,遮蔽为独立局部变量 + # (如全局 `_g_val: t.CInt` 与局部 `_g_val: int` 解析后同为 i32)。 + if nm.id is not None and trans is not None and var_ty is not None \ + and GenApi.is_global_name(trans, nm.id) == 0 \ + and GenApi.is_nonlocal_name(trans, nm.id) == 0 \ + and self.Gen.VarGen.is_module_scope(trans.SymTab) == 0: + dup_alloca: llvmlite.Value* = self.Gen.VarGen.lookup_module_var(trans.SymTab, nm.id) + if dup_alloca is not None and dup_alloca.Ty is not None: + dup_g_ty: llvmlite.LLVMType* = dup_alloca.Ty.Pointee + if dup_g_ty is not None and self._stg_ty_equal(pool, dup_g_ty, var_ty) == 0: + # 类型内容不等(_stg_ty_equal 走 TypePrint 内容比较,非地址比较: + # llvmlite 的 Int32()/Ptr() 每次构造都是新实例)。 + dup_g_buf: str = pool.alloc(256) + dup_l_buf: str = pool.alloc(256) + if dup_g_buf is not None and dup_l_buf is not None: + llvmlite.TypePrint(dup_g_buf, 256, dup_g_ty, pool) + llvmlite.TypePrint(dup_l_buf, 256, var_ty, pool) + self.Gen.TypeGenErr.fatal_error(aa, + f"重复定义:'{nm.id}' 已是模块级变量(类型 {dup_g_buf})," + f"此处又注解为 {dup_l_buf}。函数内同名注解必须与全局一致;" + f"如需独立局部变量请换名,如需修改全局请在函数内加 global 声明", + "TypeError") + # t.Callable 函数指针:注册返回类型签名(供函数指针间接调用精确返回类型) callable_ret: llvmlite.LLVMType* = self.Gen.TypeGenErr.try_extract_callable_ret(pool, annot, trans._imported_modules, trans._from_imports, trans) if callable_ret is not None: