debug(stub): 一次性插桩定位 ast.ClassDef 票名前缀分裂(定位后删除)

9994d2e 改判据后现象不变,需要在一次重建里同时看到三处事实,避免反复猜:
- TypeGenResolve._class_true_def_sha1:cls 含 "ClassDef" 时打印 HIT/MISS 与候选
  sha1、命中条目的 IR 名前缀(用 strstr 以便同时捕获 "ClassDef*" 形态);
- VpiReader._inject_reexport_class_declare:src/local 为 ClassDef 时打印调用现场
  的「源 entry 是否已注册 / 别名是否已存在」(src_entry=0 ⇒ 别名必然建不起来);
- VpiReader 的 ImportFrom 分支:判定为包 __init__ 时各打印一行(模块名、包前缀、
  子模块名与解析出的 sha1),确认包判定与子模块解析是否成立。

全部带 [DBG-P7] 前缀,便于 grep 与事后清除。
This commit is contained in:
TermiNexus committed 2026-10-02 00:32:05 +08:00
1 parent 9994d2e983
commit 96c110242e
2 files changed
+45

No files matched your search

+33
View File
@@ -2262,6 +2262,26 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*,
sub_sha1_rt = StubMergerStore.LookupSha1ByModNameSuffix(sifr_mod)
else:
sub_sha1_rt = StubMergerStore.LookupSha1ByModName(sifr_mod)
# [DBG-P7] 临时诊断(定位 ast.ClassDef 票名前缀分裂后删除):仅对判定为
# 包 __init__ 的 stub 打印一行,确认"包判定是否成立 + 子模块 sha1 解析"。
if is_pkg_init_rt != 0:
_mm_dbg: str = StubMergerStore.LookupModNameBySha1(src_sha1)
if _mm_dbg is None:
_mm_dbg = "?"
_pp_dbg: str = pkg_prefix_rt
if _pp_dbg is None:
_pp_dbg = "?"
_sm_dbg: str = sifr_mod
if _sm_dbg is None:
_sm_dbg = "?"
_sq_dbg: str = sifr_mod_q
if _sq_dbg is None:
_sq_dbg = "?"
_ss_dbg: str = sub_sha1_rt
if _ss_dbg is None:
_ss_dbg = "?"
stdio.printf("[DBG-P7] pin stub=%s mod=%s level=%d sifr=%s sifr_q=%s pkg=%s sub=%s\n",
src_sha1, _mm_dbg, sifr.level, _sm_dbg, _sq_dbg, _pp_dbg, _ss_dbg)
# [D26 fail-fast] 包 __init__ 的 from-import 解析不出子模块 sha1 时
# **不再静默跳过**:跳过会让该子模块的类一个都注册不上 → 包 stub 里
# 引用这些类的注解在后续解析时落空 → 报错点远离真因(实测:报错指向
@@ -2615,6 +2635,19 @@ def _inject_reexport_class_declare(pool: memhub.MemBuddy*,
return 0
if src_name[0] == '\0' or local_name[0] == '\0':
return 0
# [DBG-P7] 临时诊断(定位 ast.ClassDef 票名前缀分裂后删除):只盯 ClassDef,
# 打印"源 entry 是否已注册 / 别名是否已存在"——src_entry=0 即别名必然建不起来
# (上游:子模块 vpi 未注入或该类未被注册)。
if string.strcmp(local_name, "ClassDef") == 0 or string.strcmp(src_name, "ClassDef") == 0:
_se_dbg: GenTypes.StructEntry* = GenApi.find_struct_by_module(src_name, sub_sha1)
_se_ok_dbg: int = 0
if _se_dbg is not None and _se_dbg.Ty is not None:
_se_ok_dbg = 1
_al_dbg: int = 0
if GenApi.find_struct_by_module(local_name, pkg_sha1) is not None:
_al_dbg = 1
stdio.printf("[DBG-P7] reexport-call src=%s local=%s sub=%s pkg=%s src_entry=%d alias=%d\n",
src_name, local_name, sub_sha1, pkg_sha1, _se_ok_dbg, _al_dbg)
# 幂等:包 sha1 下 local_name 已注册则跳过(重复 import 不重复注册)
if GenApi.find_struct_by_module(local_name, pkg_sha1) is not None:
return 1
+12
View File
@@ -255,6 +255,18 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
if pool is None or cls_name is None or cand_sha1 is None:
return cand_sha1
e: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(cls_name, cand_sha1)
# [DBG-P7] 临时诊断(定位 ast.ClassDef 票名前缀分裂后删除):只盯 ClassDef,
# 打印"包别名 entry 是否命中"。miss ⇒ 别名没登记 ⇒ 前缀保留包 sha1(幽灵名)。
# 用 strstr 而非 strcmp:同时捕获 "ClassDef*" 形态(若尾随星号没被规则 1.6
# 剥掉,attr 会带星号 ⇒ 本条日志直接暴露"规则 1.6 没走到")。
if string.strstr(cls_name, "ClassDef") is not None:
if e is None or e.Ty is None:
stdio.printf("[DBG-P7] true_def MISS cls=%s cand=%s\n", cls_name, cand_sha1)
else:
_nm_dbg: str = llvmlite.get_struct_name(e.Ty)
if _nm_dbg is None:
_nm_dbg = "?"
stdio.printf("[DBG-P7] true_def HIT cls=%s cand=%s nm=%s\n", cls_name, cand_sha1, _nm_dbg)
if e is None or e.Ty is None:
return cand_sha1
nm: str = llvmlite.get_struct_name(e.Ty)