fix(tpc): 降级判据改用「注解形态 + 解析结果形状」,放在字段类型唯一漏斗

上一版拦截失效的原因(实测):`class_member_annotations` 全仓**只被声明与读取、从未被
写入**(Step 2 一直是空转),故依赖它的 `_HasDegradedMemberTypes` 恒为 False。改法:

1) SymbolUtils 新增两个**形状判据**(纯判定,不做类型解析):
   - IsI8DoublePtrType(T):是否 i8 系两层指针(`i8**`)= `T | t.CPtr` 在 T 类型丢失后
     退化成的形状;
   - IsClassRefPtrAnnotation(Ann):注解是否「指针包装的类引用」(rawptr[Mod.Class] /
     Mod.Class | t.CPtr;内层为非 t/c 模块的 Attribute 或首字母大写裸名)。
2) HandlesBase.CollectAnnAssignMember(字段类型的**唯一漏斗**,覆盖本地类 /
   跨模块 .vpi / 嵌套类三条写入链)新增硬判据:注解是类引用指针 **且** 解析结果正是
   `i8**` ⇒ 必属类型信息丢失,当场 fail-fast,并打出 CTypeInfo 全字段(BaseType/
   PtrCount/IsStruct/IsTypedef/IsEnum/Name)与内层名的符号表条目标志。此前的
   `_CheckPtrAnnotationKeepsClass` 只看"void 基座且无类身份",而现场这条链**带 Name/
   IsTypedef**(Attribute 分支的 typedef 出口 → BaseType=CVoid 但 Name=类名),正好漏过。
3) StructGen 删除依赖那张空表的 `_HasDegradedMemberTypes` / `_IsI8DoublePtr` /
   `_IsClassRefPtrAnnotation` 及 set_body 前的拦截(改由漏斗处兜住,不留死代码)。

现场:Generator.vp:200 `self.ExprGenFstr = SubExprGenFstr`
  → 布局槽 elements[11]=i8** 而声明 %"a7b68c79f39cb4d3.ExprGenFstr"*
This commit is contained in:
TermiNexus committed 2026-09-29 12:04:20 +08:00
1 parent 66de269ebf
commit 7167703ca7
3 files changed
+91 -84

No files matched your search

+42 -1
View File
@@ -15,7 +15,8 @@ from lib.includes.t import CTypeRegistry
from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES
from lib.core.SymbolUtils import (
IsPtrSubscriptNode, IsListAnnotation, IsCPtrMarkerNode,
FlattenUnionOperands, FixedArrayKeywordAnnotationError)
FlattenUnionOperands, IsI8DoublePtrType, IsClassRefPtrAnnotation,
FixedArrayKeywordAnnotationError)
from lib.core.VLogger import get_logger as _vlog
@@ -1091,6 +1092,46 @@ class BaseHandle:
# (llvmlite set_body 只能设一次),后期只修表不修体(现场:Generator 第 3/11
# 槽 i8**)。此处响亮失败并附判据,使降级**当场暴露**而非留到赋值时报"层数不同"。
self._CheckPtrAnnotationKeepsClass(item.annotation, TypeInfo, VarName, AnnotationText)
# 形状判据(更硬的一条):注解形态是「**指针包装的类引用**」而解析结果正是
# `i8**`(= void 基座两层,T 的类型被丢掉)⇒ 必属降级,直接响亮失败并把两侧
# 证据打全。放在字段类型的**唯一漏斗**里,覆盖全部"按注解推导成员类型"的写入链
# (本地类 / 跨模块 .vpi / 嵌套类)。
if (IsClassRefPtrAnnotation(item.annotation, self.Trans.SymbolTable)
and IsI8DoublePtrType(MemberType)):
_inner_name: str = ''
_inner_node: Any = (item.annotation.slice
if isinstance(item.annotation, ast.Subscript) else None)
if isinstance(_inner_node, ast.Attribute):
_inner_name = _inner_node.attr
elif isinstance(_inner_node, ast.Name):
_inner_name = _inner_node.id
_sym: Any = None
try:
_sym = self.Trans.SymbolTable.lookup(_inner_name) if _inner_name else None
except Exception:
_sym = None
_gen: Any = getattr(self.Trans, 'LlvmGen', None)
_structs_hit: str = (
'有' if (_gen is not None and _inner_name in getattr(_gen, 'structs', {})) else '无')
_sha1_hit: Any = (
getattr(_gen, '_struct_sha1_map', {}).get(_inner_name) if _gen is not None else None)
raise ValueError(
f"[FATAL] 成员 '{VarName}' 的注解 '{AnnotationText}' 是**类引用指针**,"
f"却被解析成 {MemberType}(void 基座两层 = 类型信息丢失)—— 拒绝降级:"
f"CTypeInfo(BaseType={getattr(TypeInfo, 'BaseType', None)} "
f"PtrCount={getattr(TypeInfo, 'PtrCount', None)} "
f"IsStruct={getattr(TypeInfo, 'IsStruct', None)} "
f"IsTypedef={getattr(TypeInfo, 'IsTypedef', None)} "
f"IsEnum={getattr(TypeInfo, 'IsEnum', None)} "
f"Name={getattr(TypeInfo, 'Name', None)});内层名='{_inner_name}' "
f"符号表[该名] => IsTypedef={getattr(_sym, 'IsTypedef', None)} "
f"BaseType={getattr(_sym, 'BaseType', None)} "
f"PtrCount={getattr(_sym, 'PtrCount', None)} "
f"IsStruct={getattr(_sym, 'IsStruct', None)} "
f"IsRenum={getattr(_sym, 'IsRenum', None)} "
f"IsModuleAlias={getattr(_sym, 'IsModuleAlias', None)};"
f"Gen.structs 命中={_structs_hit} _struct_sha1_map 命中={_sha1_hit!r}"
)
return VarName, MemberType, TypeInfo
def _CheckPtrAnnotationKeepsClass(self, Annotation: ast.AST, Info: CTypeInfo | None,