fix(exprcall): 兄弟 Mixin 兜底按调用类是否声明该方法过滤,修复 NoVTable 回归
780cd4a 用 MRO/组合类判断 _is_mixin_parent 不可靠:Combined 定义在 BaseB 之后,BaseB.caller 翻译时组合类未注册、MRO 查询失败 → 兜底静默跳过 → NoVTableCrossMixinTest 的 TPC 编译 fallback 生成不存在的 BaseB.helper(定义在 BaseA)→ ld.lld undefined symbol(回归)。
改为:调用类自身声明了该方法(class_methods 含 MethodName)但 stub 未命中(如 JsonValue.__getitem__ 跨模块 stub 注册问题)→ 不兜底,fail-fast 暴露上游 stub 问题(防误绑 HashTable,1.LOG 根因);调用类未声明(BaseB.helper / MixinC2.mid2)→ 跨 Mixin,全量遍历找定义类。保留 list 特化过滤(3fd875d)。
This commit is contained in:
1 parent
f703fdaf23
commit
8a0da29461
1 file changed
+22
-32
@@ -3165,38 +3165,28 @@ class ExprCallHandle(BaseHandle):
|
||||
method_anc = anc
|
||||
break
|
||||
if not func or len(list(func.blocks)) == 0:
|
||||
# 兄弟 Mixin 兜底:方法不在本类 MRO 链(如 BaseB 内 self.helper()
|
||||
# 调兄弟 BaseA.helper,BaseB 自身无 BaseA 的继承信息)。全局扫描
|
||||
# 已注册类找定义类,this 由 _adjust_this_for_inherited_method 按
|
||||
# 组合布局前移 sizeof(定义类 struct)。修复 TPC 编译 TPV 的
|
||||
# undefined symbol: <sha1>.BaseB.helper / StmtGenDeclMixin.translate_*。
|
||||
# 仅对普通类名兜底:泛型特化类名(list[X]/dict[K,V],含 '[')是
|
||||
# 模板容器,其特化函数(如 list[ASTptr].__getitem__)在模块中存在
|
||||
# 但绝非"兄弟 Mixin"——若不过滤,JsonValue.__getitem__ 等普通
|
||||
# 方法调用在找不到时会误绑定到 list 特化函数,this 按 list 布局
|
||||
# 前移 sizeof(list) → 运行期读 -1 崩溃(Config.vp 的
|
||||
# root.__getitem__ 根因,与 TPV CallGenCall.vp 兜底修复一致)。
|
||||
# 进一步加固:兄弟 Mixin 兜底仅在 class_name 是多继承组合类的
|
||||
# 父类(存在以 class_name 为父类的类,如 Generator 的 44 个 Mixin /
|
||||
# Combined(BaseA, BaseB))时才启用。普通类(JsonValue 等)方法
|
||||
# 未命中时不应回退到无关类——3fd875d 只过滤了 list 特化,
|
||||
# HashTable.__getitem__ 仍被误绑(JsonValue.__getitem__ 未命中时
|
||||
# 遍历 class_methods 命中 HashTable),this 前移 sizeof(HashTable)
|
||||
# =-48 → Load_project_config root.__getitem__ 读 -1 崩溃
|
||||
# (1.LOG 4c1f8f779b98eab9.HashTable._slot_hash)。
|
||||
_is_mixin_parent: bool = False
|
||||
try:
|
||||
for _s_cls in Gen.structs:
|
||||
if _s_cls == ClassName:
|
||||
continue
|
||||
if '[' in _s_cls:
|
||||
continue
|
||||
if ClassName in Gen._get_mro_chain(_s_cls):
|
||||
_is_mixin_parent = True
|
||||
break
|
||||
except Exception:
|
||||
_is_mixin_parent = False
|
||||
if _is_mixin_parent:
|
||||
# 兄弟 Mixin 兜底:仅当"调用类自身未声明该方法"时启用。
|
||||
# 判断依据 class_methods[ClassName]:
|
||||
# * BaseB.caller 调 self.helper()——BaseB 无 helper(源码未定义)
|
||||
# → 跨 Mixin → 在其它注册类中找定义类(BaseA.helper)✓
|
||||
# * JsonValue.__getitem__ 源码定义存在但 stub 未命中(如 TPV 自身
|
||||
# 编译 Config.vp 时跨模块 stub 注册/时序问题)→ 不兜底,
|
||||
# fail-fast(Undefined method)暴露上游 stub 问题——避免误绑
|
||||
# 无关类 HashTable.__getitem__(this 前移 sizeof(HashTable)=-48
|
||||
# → Load_project_config 读 -1 崩溃,1.LOG 根因;3fd875d 只
|
||||
# 过滤 list 特化,普通类仍被误绑)。
|
||||
# 注:不能用 MRO/组合类判断(Combined 定义在 BaseB 之后,BaseB.caller
|
||||
# 翻译时组合类未注册,MRO 查询不可靠——780cd4a 引入 NoVTable 回归)。
|
||||
_self_has_method: bool = False
|
||||
_cm_map = getattr(Gen, 'class_methods', None)
|
||||
if isinstance(_cm_map, dict):
|
||||
_self_methods = _cm_map.get(ClassName)
|
||||
if _self_methods:
|
||||
for _sm in _self_methods:
|
||||
if _sm == MethodName or _sm.endswith(f'.{MethodName}'):
|
||||
_self_has_method = True
|
||||
break
|
||||
if not _self_has_method:
|
||||
for _cand_cls, _cand_methods in list(Gen.class_methods.items()):
|
||||
if _cand_cls == ClassName:
|
||||
continue
|
||||
|
||||
Reference in new issue
Block a user