fix(generic): 泛型类构造 Call 实参推断同步收紧,抽出共用精确映射
CallGenCtor._infer_generic_ctor_type_arg 的 Call 分支此前与泛型函数路径同款名字子串猜测(含 Int→int、Float→double),把 CUInt64T/CInt16T 静默归成 int=i32、CFloat32T 猜成 double。改为:把被调表达式交给注解解析器,命中标量才据精确位宽映射;非标量/不可解析仍 fail-fast(保持原有"明确的类型意图却无法解析"报错)。 新增 ClassGenGeneric.infer_scalar_type_arg_from_llvm_ty 作为两处共用的唯一入口(内部走 _infer_scalar_type_name_from_spec),泛型函数路径一并改为调用它,消除重复的 arena/SpecFromLLVMType 样板,保证两处同口径。
This commit is contained in:
1 parent
9a80f1df6c
commit
28b7437e21
2 files changed
+34
-32
No files matched your search
@@ -847,35 +847,22 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
if k == ast.ASTKind.Call:
|
||||
cl_f: ast.Call* = ast.Call*(arg_node)
|
||||
if cl_f.func is not None:
|
||||
if cl_f.func.kind() == ast.ASTKind.Name:
|
||||
fn_nm: ast.Name* = ast.Name*(cl_f.func)
|
||||
if fn_nm.id is not None:
|
||||
# 与下方 Attribute 分支的 strstr 匹配一致:from t import CInt
|
||||
# 后 `CInt(0)` 的 func 是 Name("CInt"),仅精确匹配 int/float
|
||||
# 会漏判 → fail-fast 误杀(VectorGenericTest 隐式泛型推断)。
|
||||
if string.strcmp(fn_nm.id, "float") == 0 or string.strcmp(fn_nm.id, "double") == 0 or string.strstr(fn_nm.id, "Float") is not None or string.strstr(fn_nm.id, "Double") is not None:
|
||||
return "double"
|
||||
# char 内置类型(char(x) 或含 "Char" 的 t/c 类名:CChar/UChar 等)
|
||||
# → "char",与 float/double 并列(此前归 int 组丢失 i8 语义)
|
||||
if string.strcmp(fn_nm.id, "char") == 0 or string.strstr(fn_nm.id, "Char") is not None:
|
||||
return "char"
|
||||
if string.strcmp(fn_nm.id, "int") == 0 \
|
||||
or string.strstr(fn_nm.id, "Int") is not None or string.strstr(fn_nm.id, "UInt") is not None \
|
||||
or string.strstr(fn_nm.id, "Short") is not None \
|
||||
or string.strstr(fn_nm.id, "Long") is not None:
|
||||
return "int"
|
||||
elif cl_f.func.kind() == ast.ASTKind.Attribute:
|
||||
fn_at: ast.Attribute* = ast.Attribute*(cl_f.func)
|
||||
if fn_at.attr is not None:
|
||||
if string.strstr(fn_at.attr, "Float") is not None or string.strstr(fn_at.attr, "Double") is not None:
|
||||
return "double"
|
||||
# char 内置类型(char(x) 等含 "Char" 的类名)→ "char"
|
||||
if string.strstr(fn_at.attr, "Char") is not None:
|
||||
return "char"
|
||||
if string.strstr(fn_at.attr, "Int") is not None or string.strstr(fn_at.attr, "UInt") is not None or string.strstr(fn_at.attr, "Short") is not None or string.strstr(fn_at.attr, "Long") is not None:
|
||||
return "int"
|
||||
# 类型转换调用(Call)但函数名无法识别:明确的类型意图却无法解析,
|
||||
# fail-fast(返回 None ⇒ 调用方 fail-fast)。
|
||||
# 只认「被调名本身可解析为**标量类型**」的转换调用:把被调表达式交给
|
||||
# 注解解析器解析,命中标量即据其**精确位宽**经
|
||||
# ClassGenGeneric.infer_scalar_type_arg_from_llvm_ty(唯一真源)映射。
|
||||
# 彻底移除原按名字子串猜测(含 Int→int 等):它把 CUInt64T/CInt16T
|
||||
# 一律归成 int=i32(静默窄化/扩宽),CFloat32T 猜成 double。
|
||||
# 与泛型函数路径 ClassGenGeneric._infer_generic_func_type_arg 同口径。
|
||||
fk_c: int = cl_f.func.kind()
|
||||
if (fk_c == ast.ASTKind.Name or fk_c == ast.ASTKind.Attribute) and trans is not None:
|
||||
cty_c: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||||
pool, cl_f.func, trans._imported_modules, trans._from_imports, trans, 0)
|
||||
if cty_c is not None:
|
||||
ta_c: str = self.Gen.ClassGenGeneric.infer_scalar_type_arg_from_llvm_ty(pool, cty_c)
|
||||
if ta_c is not None:
|
||||
return ta_c
|
||||
# 类型转换调用(Call)但被调名无法解析为标量类型:明确的类型意图却无法
|
||||
# 解析,fail-fast(返回 None ⇒ 调用方 fail-fast)。
|
||||
self.Gen.TypeGenErr.fatal_error(arg_node, f"无法从实参推断泛型类 '{class_name}' 的类型实参,请显式标注如 {class_name}[类型](...)", "TypeError")
|
||||
return None
|
||||
# 普通变量(Name)实参:取变量条目的注解类名(与形参定义/AnnAssign 经
|
||||
|
||||
@@ -407,9 +407,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
cty_f: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(
|
||||
pool, cl_f.func, trans._imported_modules, trans._from_imports, trans, 0)
|
||||
if cty_f is not None:
|
||||
arena_c: TSpec.TypeSpecArena* = self.Gen.TypeGenBase.ensure_spec_arena()
|
||||
if arena_c is not None:
|
||||
return self._infer_scalar_type_name_from_spec(pool, TSpec.SpecFromLLVMType(arena_c, cty_f))
|
||||
return self.infer_scalar_type_arg_from_llvm_ty(pool, cty_f)
|
||||
return None
|
||||
return None
|
||||
|
||||
@@ -446,6 +444,23 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
if string.strcmp(buf, "i32") == 0: return "int"
|
||||
return None
|
||||
|
||||
def infer_scalar_type_arg_from_llvm_ty(self, pool: memhub.MemBuddy*,
|
||||
ty: llvmlite.LLVMType*) -> str:
|
||||
"""LLVM **标量**类型 → 泛型类型实参票名(精确位宽;非标量返回 None)
|
||||
|
||||
泛型函数(ClassGenGeneric._infer_generic_func_type_arg)与泛型类构造
|
||||
(CallGenCtor._infer_generic_ctor_type_arg)的 Call 实参推断共用,保证
|
||||
"转换调用实参 → 类型实参" 两处同口径(唯一真源
|
||||
_infer_scalar_type_name_from_spec)。非标量(结构体/指针/数组/函数)返回
|
||||
None ⇒ 调用方不据此推断(宁缺毋错,不按名字子串猜)。
|
||||
"""
|
||||
if pool is None or ty is None:
|
||||
return None
|
||||
arena: TSpec.TypeSpecArena* = self.Gen.TypeGenBase.ensure_spec_arena()
|
||||
if arena is None:
|
||||
return None
|
||||
return self._infer_scalar_type_name_from_spec(pool, TSpec.SpecFromLLVMType(arena, ty))
|
||||
|
||||
def _clone_funcdef_for_spec(self, pool: memhub.MemBuddy*,
|
||||
fd: ast.FunctionDef*,
|
||||
spec_base: str,
|
||||
|
||||
Reference in new issue
Block a user