fix(structgen): lookup_field_by_class 模块归属未命中回退裸名同名类(唯一时),修复 ast.Attribute 归属错位误报

- 场景:ast.Attribute(ast/exprs.vp 定义,ModuleSha1=c0def010dcebadb1)经
  lookup_field_by_class 模块归属解析,模块段 "ast" 走包名回退 → ast/__init__.vp
  的 sha1 (35245c385b0ddd7b)→ find_struct_by_module 不匹配 → 误报
  "类 ast.Attribute 未找到"(AssignGenMixin.is_cdefine_annotation 的 at.attr 触发)
- 修复:模块可解析但类未注册时,统计裸名同名类数量,唯一时回退查找字段
  (Attribute 短名无跨模块同名,安全);多同名仍 fail-fast(防 sched.Thread 顶掉)
This commit is contained in:
TermiNexus committed 2026-08-27 16:10:48 +08:00
1 parent 907f7892f9
commit ce62546e90
1 file changed
+39 -9
+39 -9
View File
@@ -141,7 +141,7 @@ class StructGenMixin:
entry_size: t.CSizeT = GenTypes.StructEntry.__sizeof__()
table_pool: memhub.MemBuddy | t.CPtr = pool
if self.StdlibAlloc != 0:
table_pool = CompilerFactory.get_perm_pool()
table_pool = CompilerFactory.factory.PermPool
if table_pool is None:
table_pool = pool
self.StructTable = table_pool.alloc(entry_size * STRUCT_MAX)
@@ -201,7 +201,7 @@ class StructGenMixin:
# 分配字段数组(1b 阶段用永久池,避免 reset 回收后 Fields 悬空)
field_size: t.CSizeT = GenTypes.FieldEntry.__sizeof__()
if self.StdlibAlloc != 0:
perm_sg: memhub.MemBuddy | t.CPtr = CompilerFactory.get_perm_pool()
perm_sg: memhub.MemBuddy | t.CPtr = CompilerFactory.factory.PermPool
if perm_sg is None:
perm_sg = pool
entry.Fields = perm_sg.alloc(field_size * FIELD_MAX)
@@ -217,7 +217,7 @@ class StructGenMixin:
# 曾读悬空 Name 越界 → G3 LinkedNode.prepend 挂起根因)
name_pool: memhub.MemBuddy | t.CPtr = pool
if self.StdlibAlloc != 0:
name_pool = CompilerFactory.get_perm_pool()
name_pool = CompilerFactory.factory.PermPool
if name_pool is None:
name_pool = pool
name_len: t.CSizeT = string.strlen(name)
@@ -253,7 +253,7 @@ class StructGenMixin:
sha1_len: t.CSizeT = string.strlen(sha1)
sha1_pool: memhub.MemBuddy | t.CPtr = pool
if self.StdlibAlloc != 0:
sha1_pool = CompilerFactory.get_perm_pool()
sha1_pool = CompilerFactory.factory.PermPool
if sha1_pool is None:
sha1_pool = pool
sha1_buf: str = sha1_pool.alloc(sha1_len + 1)
@@ -301,7 +301,7 @@ class StructGenMixin:
# 与 register_struct 的 Name 悬空同根因)
fname_pool: memhub.MemBuddy | t.CPtr = pool
if self.StdlibAlloc != 0:
fname_pool = CompilerFactory.get_perm_pool()
fname_pool = CompilerFactory.factory.PermPool
if fname_pool is None:
fname_pool = pool
name_len: t.CSizeT = string.strlen(field_name)
@@ -318,7 +318,7 @@ class StructGenMixin:
# AnnotClassName 回退、_apply_struct_defaults 的 build_gep_struct 用 fe.Ty
# 作 GEP 结果类型)解引用悬空内存 → 崩溃点漂移(json/string/builtins 之间)。
if self.StdlibAlloc != 0:
dp_pool_sg: memhub.MemBuddy | t.CPtr = CompilerFactory.get_perm_pool()
dp_pool_sg: memhub.MemBuddy | t.CPtr = CompilerFactory.factory.PermPool
if dp_pool_sg is None:
dp_pool_sg = pool
ty_copy: llvmlite.LLVMType | t.CPtr = llvmlite.DeepCopyType(dp_pool_sg, field_ty)
@@ -328,7 +328,7 @@ class StructGenMixin:
fe.Ty = field_ty
if annot_class_name is not None:
annot_len: t.CSizeT = string.strlen(annot_class_name)
annot_buf: str = CompilerFactory.get_perm_pool().alloc(annot_len + 1)
annot_buf: str = CompilerFactory.factory.PermPool.alloc(annot_len + 1)
if annot_buf is not None:
string.strcpy(annot_buf, annot_class_name)
fe.AnnotClassName = annot_buf
@@ -832,7 +832,37 @@ class StructGenMixin:
self.Gen.TypeGenErr.fatal_error(node, fb, "AttributeError")
stdlib.free(mod_buf_q)
return None
# 模块可解析但类未注册:fail-fast(暴露 vpi 注入/注册缺陷,
# 模块可解析但类未注册:先看裸名同名类是否唯一——
# 模块归属错位场景(如 "ast.Attribute":模块 'ast' 经包名
# 回退解析到 ast/__init__.vp 的 sha1,但 Attribute 类实际
# 注册在子模块 ast/exprs.vp,ModuleSha1 不匹配 → 查不到)。
# 裸名唯一时回退(Attribute 短名无跨模块同名,安全);
# 多同名时保持 fail-fast(防 sched.Thread 被顶掉的同类问题)。
same_cnt_q: int = 0
same_entry_q: GenTypes.StructEntry | t.CPtr = None
for i_sq in range(self.StructCount):
e_sq: GenTypes.StructEntry | t.CPtr = self._get_struct_entry(i_sq)
if e_sq is not None and e_sq.Name is not None:
if string.strcmp(e_sq.Name, bare_q) == 0:
same_cnt_q += 1
same_entry_q = e_sq
if same_cnt_q == 1 and same_entry_q is not None:
for fi_q2 in range(same_entry_q.FieldCount):
fe_q2: GenTypes.FieldEntry | t.CPtr = \
self._get_field_entry(same_entry_q, fi_q2)
if fe_q2 is not None and fe_q2.Name is not None:
if string.strcmp(fe_q2.Name, field_name) == 0:
stdlib.free(mod_buf_q)
return fe_q2
# 裸名类命中但字段未找到:可读化报错
viperlib.snprintf(fb, 1024,
"lookup_field_by_class: 类 '%s' 裸名回退"
"(ModuleSha1=%s, FieldCount=%d)但字段 '%s' 未找到",
class_name, mod_sha1_q, same_entry_q.FieldCount, field_name)
self.Gen.TypeGenErr.fatal_error(node, fb, "AttributeError")
stdlib.free(mod_buf_q)
return None
# 裸名也不唯一/不存在:fail-fast(暴露 vpi 注入/注册缺陷,
# 不再裸名跨库抓其他模块同名类)
viperlib.snprintf(fb, 1024,
"lookup_field_by_class: 类 '%s' 未找到(模块 '%s' 可解析"
@@ -1230,7 +1260,7 @@ class StructGenMixin:
count = PARENT_MAX
pn_pool: memhub.MemBuddy | t.CPtr = pool
if self.StdlibAlloc != 0:
pn_pool = CompilerFactory.get_perm_pool()
pn_pool = CompilerFactory.factory.PermPool
if pn_pool is None:
pn_pool = pool
arr: t.CSizeT | t.CPtr = pn_pool.alloc(8 * count)