refactor(TypeGenResolve): 裸类名恒为原型(struct 本身),删除 5 处 HasNew 自动升指针
口径(用户 2026-10-01 定):**裸类名注解 = 原型(struct 本身,类型/布局语义)**,
堆对象引用必须显式写 `T*` / `T | t.CPtr` / `rawptr[T]`。旧行为"有 __new__ 的类
(堆对象)裸名 ⇒ Ptr(struct)"是为兼容 `d: dict = dict(bd)` 这类"裸名 + 构造"写法
而设,代价是同一类型两种写法分裂:
includes/json/__init__.vp:79 `def __getitem__(...) -> 'JsonValue' | t.CPtr`
左边(引号字符串注解)先被解析成 Ptr(struct),联合分支再包一层 ⇒ JsonValue**
而 `cur: JsonValue*` 是 JsonValue* ⇒ :90 `return cur` 报
「指针层数不同(源 1 级 → 目标 2 级)」(660427f 已在联合分支做过吸收,
本次从源头统一:裸名不再自动升指针,吸收那条规则对裸名侧自然不再触发)。
改动(resolve_annotation_type 的裸名/限定名分支,共 5 处,全部去掉 HasNew 分支):
1. `{16hex}.Class` 已归一前缀名分支(原 :2768-2770)
2. 本模块自有类分支(原 :2806-2814,删掉那段"有 __new__ ⇒ Ptr"的注释与分支)
3. from-import 归属分支(原 :2832-2834)
4. 可见结构体裸名分支(原 :2842-2844)
5. `mod.Class` 限定名分支(原 :3040-3044)
影响面盘点(静态扫描 474 个 .vp):本文件内"裸堆类名注解"16 处、跨文件候选 63 处
(含同名跨模块误报),典型:
includes/hashtable.vp:45 ht: HashTable = HashTable(mb)
includes/_dict.vp:29 d: dict = dict(mb)
Test/BuiltinDecoratorTest/App/main.vp:33/36/68/98/137/180/184/194/199/234/241/248
TransPyV/Test/App/new_test.vp:81/93/105
Test/{ClassArrayTest,StructTest,ClosureTest2,StringIterTest}/App/*.vp 若干
这些站点需按新口径显式补 `*`(或改用 `T | t.CPtr`);真实集合以编译器 fail-fast
报错为准(同名跨模块无法静态判定归属)。
TPC 侧核查结论:**无需改动,TPC 本就同口径**。证据:
1. 全仓 `HasNew|has_new` 仅 8 处,全在**构造路径**——HandlesAnnAssign.py:401
(`list[T] = [...]` 字面量构造)、HandlesExprCall.py:5105/5161/5170/5198/5235/5263
(`ClassName(...)` 构造,`_HandleClassNewLlvm`);**注解解析链上一处都没有**。
2. 规范注解解析 `TypeAnnotationResolver._from_node_name`(裸 Name)、
`_from_node_attribute`(mod.Class)、`_from_node_constant`('X' 引号注解)
全程不查 __new__,裸类名一律 PtrCount=0(原型)。
3. 局部变量路径 HandlesAnnAssign.py:678-683 显式把裸类名 PtrCount 由 1 改回 0
("纯结构体名注解应为值类型"),仅保留 vtable 类为指针;模块级全局
HandlesAssign.py:1840-1856 亦按 struct 值类型建 GlobalVariable。
4. 符号表类条目 PtrCount 默认 0(SymbolTable._InsertClassSymbol:489-518 从不设
PtrCount;TypeSpec.py:139 默认 0)。
因此 `d: dict = dict(mb)`(dict 有 __new__、非 vtable 类)在 TPC 侧本来就是
struct 值语义,与本次 TPV 改动后的口径一致。json/__init__.vp 的
`'JsonValue' | t.CPtr`(定义端 0+1 层、声明端裸类引用吸收 1 层)两侧都已是
`%"…JsonValue"*`(1 层),本次 TPV 改动后亦对齐。
待验证(不自行执行编译命令):先重编译 TransPyV,再跑
JsonTest / DictTest / StructTest / BuiltinDecoratorTest / ClassArrayTest
预期先出现一批"注解需补 `*`"的报错——那正是本次口径变更要求的显式化。
This commit is contained in:
1 parent
660427f759
commit
875a9beb08
1 file changed
+15
-20
@@ -2765,8 +2765,10 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
sp_sha_buf2[sp_len2 - 1] = '\0'
|
||||
sp_entry2: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(nm.id + sp_len2, sp_sha_buf2)
|
||||
if sp_entry2 is not None and sp_entry2.Ty is not None:
|
||||
if sp_entry2.HasNew != 0:
|
||||
return llvmlite.Ptr(pool, sp_entry2.Ty)
|
||||
# 裸类名恒为**原型**(struct 本身,值/布局语义),不再看 HasNew:
|
||||
# 堆对象引用必须显式写 `T*` / `T | t.CPtr` / `rawptr[T]`
|
||||
# (用户 2026-10-01 定;TPC 侧注解链路本无 __new__ 升指针逻辑,
|
||||
# 天然同口径,故 TPC 无需同步改)。
|
||||
return sp_entry2.Ty
|
||||
# 兜底:按完整前缀名直接查(部分注册键即全名)
|
||||
sp_full2: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(nm.id)
|
||||
@@ -2803,14 +2805,14 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
if trans is not None and trans.ModuleSha1 is not None:
|
||||
own_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(nm.id, trans.ModuleSha1)
|
||||
if own_entry is not None and own_entry.Ty is not None:
|
||||
# 有 __new__ 的类(堆对象)注解 → Ptr(struct)(引用语义,对齐 TPC)。
|
||||
# 否则无 __new__ 的类(栈对象,如 Point)保持 struct 值语义:
|
||||
# 构造返回栈 alloca 指针,赋给 struct 值变量时 coerce load 拷贝。
|
||||
# 背景:d: dict = dict(bd) 的 dict 是堆对象(__new__ 分配),
|
||||
# 裸名注解按值解析会让 sub: dict = sub_p 把 i8* 当 struct 解引用
|
||||
# 崩溃(DictTest Test 13)。
|
||||
if own_entry.HasNew != 0:
|
||||
return llvmlite.Ptr(pool, own_entry.Ty)
|
||||
# 裸类名恒为**原型**(struct 本身):注解说的是"类型/布局",
|
||||
# 不再按 HasNew 自动升成 Ptr(struct)。堆对象引用一律显式写
|
||||
# `T*` / `T | t.CPtr` / `rawptr[T]`(用户 2026-10-01 定;
|
||||
# TPC 侧注解链路本无 __new__ 升指针逻辑,天然同口径,
|
||||
# 故 TPC 无需同步改)。旧行为(有 __new__ ⇒ Ptr(struct))是
|
||||
# 为兼容 `d: dict = dict(bd)` 这类"裸名 + 构造"写法而设,
|
||||
# 代价是同一类型出现"裸名=指针 / 联合=再加一层"的分裂
|
||||
# (现场 includes/json/__init__.vp:90 CastError)。
|
||||
return own_entry.Ty
|
||||
# from-import 归属查找:注解里的裸名(或 import 别名)经 from_imports 定位到
|
||||
# 定义模块,再按 (name, sha1) 精确取类——这是 stub 注入场景的正解:此刻
|
||||
@@ -2829,18 +2831,12 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
if fi_sha1 is not None:
|
||||
fi_entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(nm.id, fi_sha1)
|
||||
if fi_entry is not None and fi_entry.Ty is not None:
|
||||
if fi_entry.HasNew != 0:
|
||||
return llvmlite.Ptr(pool, fi_entry.Ty)
|
||||
# 裸类名恒为原型(见上方同口径注释)
|
||||
return fi_entry.Ty
|
||||
if self.Gen.StructGen.is_struct_visible(nm.id) != 0:
|
||||
struct_ty: llvmlite.LLVMType* = self.Gen.StructGen.get_struct_type(nm.id)
|
||||
if struct_ty is not None:
|
||||
nm_entry_s: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_type(struct_ty)
|
||||
nm_has_new_s: int = 0
|
||||
if nm_entry_s is not None:
|
||||
nm_has_new_s = nm_entry_s.HasNew
|
||||
if nm_has_new_s != 0:
|
||||
return llvmlite.Ptr(pool, struct_ty)
|
||||
# 裸类名恒为原型(见上方同口径注释):不再因 HasNew 升成 Ptr
|
||||
return struct_ty
|
||||
# 枚举类(t.CEnum)裸名注解 → 底层整数类型
|
||||
# 如 fat32_types.vp 内部 `res: FRESULT = ...`(FRESULT 是枚举非结构体)
|
||||
@@ -3039,8 +3035,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
return full_ty_v
|
||||
mod_entry_v: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(at.attr, mod_sha1_v)
|
||||
if mod_entry_v is not None and mod_entry_v.Ty is not None:
|
||||
if mod_entry_v.HasNew != 0:
|
||||
return llvmlite.Ptr(pool, mod_entry_v.Ty)
|
||||
# 裸类名(含 mod.Class 限定名)恒为原型(见上方同口径注释)
|
||||
return mod_entry_v.Ty
|
||||
# 模块可解析但类未注册:不裸名回退(防跨库抓错),
|
||||
# 落到下方枚举/typedef 尝试;struct 缺失由调用侧暴露
|
||||
|
||||
Reference in new issue
Block a user