diff --git a/App/lib/Stub/StubGen/VpiReader.vp b/App/lib/Stub/StubGen/VpiReader.vp index 7f45b31..987c4cd 100644 --- a/App/lib/Stub/StubGen/VpiReader.vp +++ b/App/lib/Stub/StubGen/VpiReader.vp @@ -1605,19 +1605,19 @@ def _resolve_vpi_ret_annot_str(pool: memhub.MemBuddy*, if first_ty is not None: # 复刻定义侧规则(N12/N13):限定名 / 白名单裸标量 / 已注册结构体 / 可解析的非指针裸 typedef 别名 → 保留 pointee; # 其余(解析失败、裸枚举名、指针别名)→ 联合坍缩为 i8*,与定义侧 resolve_annotation_type 对称(两侧同型即收敛)。 - # 指针别名(first_td 不置位,如 VOIDPTR = CVoid|CPtr → i8*):`| t.CPtr` **追加 1 层** → i8**(不吸收); - # 仅当 pointee 命中 find_struct_by_type(类引用语义)时吸收 1 层,其余 ⇒ Ptr(first_ty)(与定义侧指针层数口径同源)。 + # 指针别名(first_td 不置位,如 VOIDPTR = CVoid|CPtr → i8*):`| t.CPtr` + # **恒追加恰好 1 层** → i8**(不吸收);指针型 T 同理(见下)。 if first_qual != 0 or first_wl != 0 or first_td != 0: return llvmlite.Ptr(pool, first_ty) if first_ty.kind() == llvmlite.LLVMType.Struct: return llvmlite.Ptr(pool, first_ty) if first_ty.kind() == llvmlite.LLVMType.Ptr: - match first_ty: - case llvmlite.LLVMType.Ptr(pointee_v): - if GenApi.find_struct_by_type(pointee_v) is not None: - return first_ty - case _: - pass + # `| t.CPtr` **恒追加恰好 1 层**(与定义侧 TypeGenResolve 的 BinOp 分支同口径): + # 这里原先还做"pointee 命中 find_struct_by_type(类引用语义)就吸收 1 层", + # 那是"裸类名自动升指针"时代的补偿,自裸类名恒为**原型 struct** 后已无对象; + # 而泛型形参实例化为指针类型时(T 的实参文本 `{sha}.AST*`)first_ty 正是 + # Ptr(已注册 struct) ⇒ 误吸收把 `T*` 降成 AST*(应为 AST**), + # 现场 includes/_list.vp:54 `elem_ptr[0] = item`。 return llvmlite.Ptr(pool, first_ty) return i8_ptr_ty return i8_ptr_ty diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index d51e07c..36f1aee 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -3161,8 +3161,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 判定该裸名是否可解析,命中即保留已解析类型参与「基类型 + 指针层数」合并 # (对齐 TPC HandlesTypeMerge._MergeAllComponentTypes)。 # 指针层数口径(本处 / VpiReader 注入侧 / 调用侧三处必须同步):`| t.CPtr` - # 恒为"追加 1 层指针",唯一例外是 struct 引用语义时吸收这 1 层 - # (判据 = Ptr 的 pointee 是否为已注册 struct,find_struct_by_type 命中即吸收)。 + # **恒为"追加恰好 1 层指针",无例外**——裸类名恒为原型 struct, + # `X | t.CPtr` 由 Ptr(struct) 天然得到 X*,不再需要"pointee 是已注册 + # struct 就吸收这 1 层"的旧补偿(该补偿曾把指针型 T 的 `T*` 降一层)。 if keep_other_ty == 0 and other_node is not None and other_node.kind() == ast.ASTKind.Name: other_nm_td: ast.Name* = ast.Name*(other_node) if other_nm_td.id is not None: @@ -3205,28 +3206,21 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # 回退 Ptr(i8) 由 AnnotClassName 恢复 + 多遍注册收敛 # 处理,禁止 fail-fast(误杀合法前向引用)。 return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - # struct 引用语义吸收(本文件 :3219-3221 早已写明、此前未实现的 - # 那条规则):other_ty 若已是「指向已注册 struct 的指针」,说明 - # 该侧裸类名已按**引用语义**解析过(有 __new__ 的堆类,Name/ - # Attribute 分支直接给 Ptr(struct),见 :2806-2813、:3040-3044) - # ⇒ `| t.CPtr` 不再追加一层,否则多一层指针。 - # 三种写法必须同型(用户 2026-09-30 定:统一为 T*): + # `X | t.CPtr` **恒追加恰好 1 层**(用户口径,与 rawptr[T]/t.CPtr[T] 下标形 + # 以及 `_parse_type_string` 的 `T*` 反解析三处同源): # T* ≡ rawptr[T] ≡ t.CPtr[T] ≡ T | t.CPtr - # 现场:includes/json/__init__.vp:90 `return cur` - # `def __getitem__(...) -> 'JsonValue' | t.CPtr`(**引号字符串** - # 注解,左边是 Constant 不是 Name —— 绕过了上面 :3176 那段 - # "Name 必须已注册 struct 否则丢弃"的守卫,于是带着 Ptr(struct) - # 走到这里再包一层 ⇒ JsonValue**),而 `cur: JsonValue*` 是 - # JsonValue* ⇒ CastError「指针层数不同(源 1 级 → 目标 2 级)」。 - # 之所以只在引号写法暴露:裸名写法会在 :3222-3239 被判定 - # td_res_is_ptr=1 → other_ty 置 None → 走 :3254 回退取 struct 再包 - # 一层,恰好抵消;引号写法绕过了那条路径。 - match other_ty: - case llvmlite.LLVMType.Ptr(pointee_ab): - if self.Gen.StructGen.find_struct_by_type(pointee_ab) is not None: - return other_ty - case _: - pass + # 这里原先还有一段"struct 引用语义吸收"(other_ty 若已是 Ptr(已注册 struct) + # 就直接返回它、吞掉 CPtr 这层),那是"裸类名自动升指针"时代的补偿: + # 当时裸类名/引号注解解析成 Ptr(struct),所以要吸收;自 2026-10-01 起 + # 裸类名恒为**原型 struct**(见本文件 Name/Attribute 各分支), + # `X | t.CPtr` 由 Ptr(struct) 天然得到 X*,吸收已无正当对象 + # (json/__init__.vp:90 的引号注解 `'JsonValue' | t.CPtr` 现在 other_ty + # 就是 struct,吸收本就不触发,删除后行为不变)。 + # 而**泛型形参实例化为指针类型**时(`list[rawptr[AST]]` 里 `T` 的实参文本是 + # `{sha}.AST*`,parser 把源码 `T*` 解析成 BinOp `T | t.CPtr`)other_ty 正是 + # Ptr(已注册 struct) ⇒ 误吸收把 `T*` 降成 AST*(应为 AST**), + # 现场 includes/_list.vp:54 `elem_ptr[0] = item` 被误判为"左值元素是对象 + # AST(48 字节)、右值是指针"而 fail-fast。 return llvmlite.Ptr(pool, other_ty) # t.CPtr[...] 下标指针标记(普通 _is_cptr_marker 不识别 Subscript):