diff --git a/lib/Projectrans/DeclarationGenerator.py b/lib/Projectrans/DeclarationGenerator.py index 39b4f88..e1aef71 100644 --- a/lib/Projectrans/DeclarationGenerator.py +++ b/lib/Projectrans/DeclarationGenerator.py @@ -829,14 +829,42 @@ class DeclarationGenerator: attr_name: str = item.targets[0].attr if attr_name in seen_member_names: continue - InferredType: str = 'i32' - if item.value and isinstance(item.value, ast.Constant): - if isinstance(item.value.value, float): - InferredType = 'float' - elif isinstance(item.value.value, bool): - InferredType = 'i8' - elif isinstance(item.value.value, str): + # 不再兜底 i32:只认**能唯一确定**的取值形态,推不出即响亮失败。 + # 规则表必须与定义端 HandlesClassDef._scan_node_for_self_assign 的 + # Assign 分支**逐条一致**(stub 与定义端 struct 布局必须同源, + # 少/多一个槽 ⇒ 跨模块字段偏移整体错位): + # 整型/布尔字面量 → 'i32'(定义端 bool 走 int 分支); + # 浮点字面量 → 'double'(定义端 DoubleType;此前这里写 'float' + # = f32,与定义端 8 字节不一致);字符串字面量 → 'i8*'。 + # 注:`self.X = <带注解形参>` / 白名单调用(float()/double()/char()/ + # int()…/len())在定义端可定型,本函数**拿不到**符号表故不在此推 + # (这些形态一旦出现会被定义端接受,而 stub 这里判不了); + # 另外方法体内的裸 `self.X = ...` 已被上方 seen_member_names 过滤 + # (只对**本类自有声明**判重,不含继承字段)——若贸然放行, + # 继承字段(如 G4Node.Next)会被当成自有字段重复加一个槽, + # 反而制造布局分叉。要放行必须先在此补"祖先字段名"判定。 + InferredType: str | None = None + if item.value is not None and isinstance(item.value, ast.Constant): + _v: object = item.value.value + if isinstance(_v, bool): + InferredType = 'i32' + elif isinstance(_v, int): + InferredType = 'i32' + elif isinstance(_v, float): + InferredType = 'double' + elif isinstance(_v, str): InferredType = 'i8*' + if InferredType is None: + _vt: str = '' + try: + _vt = ast.unparse(item.value) if item.value is not None else '<无值>' + except Exception: + _vt = '<无法反解析>' + raise ValueError( + f"[FATAL] 类 '{node.name}' 的字段 '{attr_name}' 在 stub 声明里" + f"推不出类型(`self.{attr_name} = {_vt}`,行 " + f"{getattr(item, 'lineno', 0)})——拒绝静默写成 i32。" + f"请在类体声明该字段并给注解。") member_types.append(InferredType) else: member_types.append('i32') diff --git a/lib/core/Handles/HandlesClassDef.py b/lib/core/Handles/HandlesClassDef.py index 8286029..8794dc3 100644 --- a/lib/core/Handles/HandlesClassDef.py +++ b/lib/core/Handles/HandlesClassDef.py @@ -1407,11 +1407,29 @@ class ClassHandle(BaseHandle): and target.value.id == 'self'): VarName = target.attr if VarName not in existing_members: - MemberType = ir.IntType(32) - if node.value: + # 类型判定:只接受**能唯一确定**的取值形态(下表);推不出即 + # fail-fast,绝不静默产出 i32 槽(项目约定:类型信息缺失立即 + # 终止;与同函数 `self.X: T` 分支 :1356-1386 同口径)。 + # 同族现场:`free_lists: uint64*` 被当成 i32 后, + # `self.free_lists = base`(i8*) 误报"指针隐式转整数已禁止"。 + # 【必须与 DeclarationGenerator._CollectOwnMemberTypes 的 + # 同名规则逐条一致】否则 stub 与定义端 struct 布局分叉 + # (stub 少/多一个槽 ⇒ 跨模块字段偏移整体错位): + # 整型字面量 → i32;布尔字面量 → i32(Python 中 bool 是 int + # 子类,维持既有 int 分支语义);浮点字面量 → double; + # 字符串字面量 → i8*;值为**本方法带注解的形参** → 该形参类型; + # 白名单调用 float()/double() → double、char() → i8、 + # int()/long()/short() → i32、`x.len()` → i32。 + # 其余(None 字面量、BinOp、任意调用/属性链…)→ fail-fast: + # 这些形态推不出成员类型,静默 i32 只会把错误推到下游 + # (写指针值 → "指针隐式转整数已禁止")。 + MemberType: ir.Type | None = None + if node.value is not None: try: if isinstance(node.value, ast.Constant): - if isinstance(node.value.value, int): + if isinstance(node.value.value, bool): + MemberType = ir.IntType(32) + elif isinstance(node.value.value, int): MemberType = ir.IntType(32) elif isinstance(node.value.value, float): MemberType = ir.DoubleType() @@ -1441,6 +1459,35 @@ class ClassHandle(BaseHandle): except Exception as _e: if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") + if MemberType is None: + _src_f: str = getattr(Gen, '_current_source_file', '') or '' + _ln_f: int = getattr(node, 'lineno', 0) or 0 + _col_f: int = getattr(node, 'col_offset', -1) + # 行号还原:AST 行号含 _inject_auto_imports 注入的 N 行 + _off_f: int = int(getattr(self.Trans, '_line_offset', 0) or 0) + if _off_f > 0 and _ln_f > _off_f: + _ln_f -= _off_f + _code_f: str = '' + try: + _code_f = (Gen._get_source_line(_ln_f) or '').strip() + except Exception: + _code_f = '' + _val_txt: str = '' + try: + _val_txt = ast.unparse(node.value) if node.value is not None else '<无值>' + except Exception: + _val_txt = '<无法反解析>' + _msg_f: str = ( + f"类 '{ClassName}' 的字段 '{VarName}' 没有声明类型" + f"(既不在类体注解、也不在祖先中),且首次赋值 " + f"`self.{VarName} = {_val_txt}` 的取值形态推不出成员类型" + f"——拒绝静默当成 i32(那会把错误推到下游:写指针值时报" + f"「指针隐式转整数已禁止」)。请在类体声明该字段并给注解" + f"(如 `{VarName}: t.CInt32T` / `{VarName}: t.CPtr`)," + f"或在赋值处给出可定型的取值。" + f"位置 {_src_f}:{_ln_f}:{_col_f}") + _vlog().compile_error(_msg_f, _src_f, _ln_f, _code_f) + sys.exit(1) Gen.class_members[ClassName].append((VarName, MemberType)) Gen.class_member_signeds[ClassName][VarName] = None Gen.class_member_bitfields[ClassName][VarName] = 0