fix(call): 泛型模板的前向声明占位不再阻断构造期类型实参推断

注解 vector.Vector | CPtr(无实参)会经 TypeGenResolve 登记不透明前向声明占位 {sha}.Vector(IsForwardDecl=1)。模块限定构造 vector.Vector(...) 在 CallGenMixin 命中该占位后,gen_ctor_entry != None 使泛型推断分支(struct_ty is None and gen_ctor_entry is None)被整段跳过,静默按普通结构体/函数构造并产出裸泛型基类对象 → 后续方法调用触发 D25 接收者 fail-fast(VectorGenericTest 根因)。改为:命中项是前向声明占位且类名为已注册泛型模板时,不锁定 struct_ty/gen_ctor_entry,放行泛型推断按实参(_hint: T)特化;裸名分支与模块限定分支同口径。
This commit is contained in:
TermiNexus committed 2026-10-03 10:18:29 +08:00
1 parent 53ba4e48bd
commit 4c114d8875
1 file changed
+16 -1
+16 -1
View File
@@ -282,6 +282,12 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
gen_ctor_entry = self.Gen.StructGen.find_struct_by_module(func_name, trans.ModuleSha1)
if gen_ctor_entry is None:
gen_ctor_entry = self.Gen.StructGen.find_struct(func_name)
# 前向声明占位(裸泛型模板注解 `Class` 无实参时由 TypeGenResolve 登记)
# 不是真实结构体定义:不作为裸名构造的 struct_ty,交由下方泛型推断按实参
# 特化(与模块限定分支同口径)。
if gen_ctor_entry is not None and gen_ctor_entry.IsForwardDecl != 0 \
and self.Gen.ClassGenGeneric._find_generic_template(func_name) is not None:
gen_ctor_entry = None
if gen_ctor_entry is not None:
struct_ty = gen_ctor_entry.Ty
elif trans is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
@@ -398,7 +404,16 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# 支持模块限定调用(vector.Vector(...)):func_name 是 attr("Vector"),
# 需确认模块已导入(模板查找兜底——普通函数如 stdlib.free 的 attr 找
# 不到模板 → 回落普通调用)。
if struct_ty is None and gen_ctor_entry is None and trans is not None:
# 前向声明占位(注解 `Mod.Class` 未带类型实参时,TypeGenResolve 会登记一个
# 不透明的 `{sha}.Class` 条目,IsForwardDecl=1)不是真实结构体定义。当该类名
# 是已注册泛型模板时,占位不得阻断下方泛型推断:否则 `vector.Vector(...)` 会
# 被静默当普通结构体/函数构造处理,造出裸泛型基类对象,随后方法调用触发
# D25 接收者 fail-fast(VectorGenericTest 根因)。
gen_ctor_is_fwd_generic: int = 0
if gen_ctor_entry is not None and gen_ctor_entry.IsForwardDecl != 0:
if self.Gen.ClassGenGeneric._find_generic_template(func_name) is not None:
gen_ctor_is_fwd_generic = 1
if struct_ty is None and (gen_ctor_entry is None or gen_ctor_is_fwd_generic != 0) and trans is not None:
is_gen_bare: int = 0
if cl.func is not None and cl.func.kind() == ast.ASTKind.Name:
is_gen_bare = 1