diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index 32ab540..49a092a 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -1599,6 +1599,57 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): if nm.id is None or string.strcmp(nm.id, "t") != 0: return 0 return 1 + def _ptr_subscript_absorbs_class(self, slice_node: ast.AST*, + resolved: llvmlite.LLVMType*) -> int: + """`rawptr[T]` / `t.CPtr[T]` 的切片 T 是**裸类引用**时是否吸收该层指针(1=吸收)。 + + 语义真源:`rawptr[T]` ≡ `t.CPtr[T]` ≡ 源码联合写法 `T | t.CPtr` + (TPC 侧 SymbolUtils.IsPtrSubscriptNode 文档),三者必须得到**同一类型**。 + 联合写法在本文件 BinOp 分支得到的是「裸类名先被丢弃、再按类名取 struct 包一层」 + ⇒ `X*`(见 :2682-2684 的口径注释与 :2703-2720 的回退);而 rawptr/CPtr + 下标分支此前无脑 `Ptr(resolve(T))`,对「有 __new__ 的堆类」(本文件 Name 分支 + :2269-2277 已把裸类名解析为 Ptr(struct))就多包一层 ⇒ `X**` + (现场:includes/ast/tokens.vp:217 `ptr: rawptr[Token] = pool.alloc(...)` + 目标 %"…Token"** vs 源 i8* → CastError)。 + + 判据(两条件同时成立才吸收,与 BinOp 分支的"Ptr 的 pointee 是否为已注册 + struct,find_struct_by_type 命中即吸收"逐字同源): + ① 切片不是**用户写明的指针包装**——联合写法(BinOp)与嵌套指针下标 + (`rawptr[...]` / `t.CPtr[...]` / 裸名 `CPtr[...]`)的层数由用户指定, + 必须逐层外包(`rawptr[rawptr[X]] → X**`、`t.CPtr[t.CPtr] → i8**`); + ② 解析结果已是 `Ptr(已注册 struct)`——即切片本身就是类引用; + `str`/`bytes`(Ptr(i8))与标量(非指针)不满足 ⇒ 保持 + `rawptr[int] → i32*`、`rawptr[str] → i8**`(与 TPC 同口径)。 + + 纯判据:不发射类型、不改动任何已解析结果。 + """ + if slice_node is None or resolved is None: + return 0 + k_sl: int = slice_node.kind() + if k_sl == ast.ASTKind.BinOp: + return 0 + if k_sl == ast.ASTKind.Subscript: + sub_sl: ast.Subscript* = ast.Subscript*(slice_node) + if sub_sl.value is not None: + vk_sl: int = sub_sl.value.kind() + if vk_sl == ast.ASTKind.Name: + vn_sl: ast.Name* = ast.Name*(sub_sl.value) + if vn_sl.id is not None: + if string.strcmp(vn_sl.id, "rawptr") == 0 \ + or string.strcmp(vn_sl.id, "CPtr") == 0: + return 0 + elif vk_sl == ast.ASTKind.Attribute: + va_sl: ast.Attribute* = ast.Attribute*(sub_sl.value) + if va_sl.attr is not None and string.strcmp(va_sl.attr, "CPtr") == 0: + return 0 + match resolved: + case llvmlite.LLVMType.Ptr(pointee_ab): + if pointee_ab is not None: + if self.Gen.StructGen.find_struct_by_type(pointee_ab) is not None: + return 1 + case _: + pass + return 0 def _is_cvoid_marker(self, node: ast.AST*, imported_modules: str) -> int: """检测节点是否为 CVoid 指针标记,返回 1=是 / 0=否""" @@ -2862,11 +2913,15 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # rawptr[T] 内建裸指针:等价 t.CPtr[T] → Ptr(T)(T 自身可含指针层级)。 # 与 t.CPtr[T] 语义一致;不处理则泛型特化/builtins 兜底失败 → # "函数返回类型解析失败:注解不可解析"。 + # T 是**裸类引用**时(已是 Ptr(struct))吸收这一层:`rawptr[X]` + # ≡ `X | t.CPtr` ≡ X*(不是 X**),见 _ptr_subscript_absorbs_class。 if string.strcmp(gen_nm.id, "rawptr") == 0: if sub.slice.kind() != ast.ASTKind.Tuple: rp_elem: llvmlite.LLVMType* = self.resolve_annotation_type(pool, sub.slice, imported_modules, from_imports, trans, depth + 1) if rp_elem is None: return None + if self._ptr_subscript_absorbs_class(sub.slice, rp_elem) != 0: + return rp_elem return llvmlite.Ptr(pool, rp_elem) return None gen_ty_nm: llvmlite.LLVMType* = self._resolve_generic_subscript_ty(pool, sub, gen_nm.id, trans, @@ -2925,6 +2980,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): return llvmlite.Ptr(pool, llvmlite.Int8(pool)) # 指针类型: t.CPtr[T] → Ptr(T)(T 自身可含指针层级):t.CPtr[t.CPtr] → i8**, # t.CPtr[int] → i32*(DeclarationGenerator.py L1014-1016 文档化语法)。 + # T 是**裸类引用**时(已是 Ptr(struct))吸收这一层:t.CPtr[X] ≡ X | t.CPtr + # ≡ X*(不是 X**),见 _ptr_subscript_absorbs_class。 if string.strcmp(arr_at.attr, "CPtr") == 0: if string.strcmp(arr_val_name.id, "t") != 0 and string.strcmp(arr_val_name.id, "c") != 0 \ and self.Gen.ImportsGen.is_module_imported(imported_modules, arr_val_name.id) == 0: @@ -2936,6 +2993,8 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase): # Phase 1a 无 vpi 注入时依赖 typedef 的类会被跳过)。与裸名 CArray 路径及 # ClassGenDef 字段 pending 机制一致;真实类型错误由 Phase A 收敛检查暴露。 return None + if self._ptr_subscript_absorbs_class(sub.slice, inner_cptr_ty) != 0: + return inner_cptr_ty return llvmlite.Ptr(pool, inner_cptr_ty) if string.strcmp(arr_at.attr, "CArray") != 0: self.Gen.TypeGenErr.fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray / t.Callable)")