diff --git a/App/lib/core/Gen/Call/CallGenCtor.vp b/App/lib/core/Gen/Call/CallGenCtor.vp index 37e2499..f59a422 100644 --- a/App/lib/core/Gen/Call/CallGenCtor.vp +++ b/App/lib/core/Gen/Call/CallGenCtor.vp @@ -1016,10 +1016,52 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase): nw_bc: mlirlite.Value* = mlirlite.build_bitcast(builder, new_ptr, nw_ty) if nw_bc is not None: storage_ptr = nw_bc - # call __before_init__(storage_ptr) (auto-generated by TransPyV, zero-fills) - self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans, None, gc_volatile) + # 有 __init__ 才调 __before_init__/__init__(与非泛型 _translate_struct_ctor 的 is_oop 判据一致): + # ClassGenVTable 只对"有方法"的类生成 __before_init__,无条件调用会在无方法类(如 Box[T])上 + # 产生 undefined symbol(__before_init__ / __init__ 都没有定义)。 + gi_has_init: int = 0 + if struct_entry is not None: gi_has_init = struct_entry.HasInit + if gi_has_init == 0: + # 特化类的 HasInit 可能没被传播:再按非泛型路径同口径查"该方法是否真的存在" + # (模块内声明 或 全局默认参数表),避免有 __init__ 的泛型类被漏掉。 + init_lk: str = pool.alloc(256) + if init_lk is not None: + viperlib.snprintf(init_lk, 256, "%s.__init__", spec_name) + if self.find_func_in_module(mod, init_lk) is not None: gi_has_init = 1 + elif self.Gen.CallGenLeafKit.find_func_defaults(init_lk) is not None: gi_has_init = 1 + if gi_has_init != 0: + # call __before_init__(storage_ptr) (auto-generated by TransPyV, zero-fills) + self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans, None, gc_volatile) - # call __init__(storage_ptr, *args) (arg_count = slots 0..highest filled) - self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__init__", storage_ptr, extra_args, arg_count, trans, None, gc_volatile, gc_arg_nodes) + # call __init__(storage_ptr, *args) (arg_count = slots 0..highest filled) + self.Gen.CallGenCall._call_method_on_ptr(pool, builder, mod, spec_name, "__init__", storage_ptr, extra_args, arg_count, trans, None, gc_volatile, gc_arg_nodes) + elif has_new_flag == 0: + # 无 __init__ 也无 __new__:按字段顺序逐字段 store(与非泛型路径同语义;字段 0 若是 + # __vtable__ 占位则跳过)。这条分支保证 `Box[int](7)` 仍然把 7 写进字段 v。 + for ai_sf in range(can): + arg_sf: ast.AST* = cargs.get(ai_sf) + if arg_sf is None: continue + fe_sf: GenTypes.FieldEntry* = None + if struct_entry is not None: + tidx_sf: int = 0 + for fi_sf in range(struct_entry.FieldCount): + cand_sf: GenTypes.FieldEntry* = self.Gen.StructGen._get_field_entry(struct_entry, fi_sf) + if cand_sf is None: continue + cn_sf: str = self.Gen.StructGen.get_field_name_ptr(cand_sf) + if cn_sf is not None and string.strcmp(cn_sf, "__vtable__") == 0: continue + if tidx_sf == ai_sf: + fe_sf = cand_sf + break + tidx_sf += 1 + else: fe_sf = self.Gen.StructGen.get_field_by_index(spec_name, ai_sf) + if fe_sf is None: + self.Gen.TypeGenErr.fatal_error(arg_sf, f"Generic class ctor '{spec_name}': too many arguments (field index out of range)", "TypeError") + continue + av_sf: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, arg_sf, None, 0, trans, fe_sf.Ty) + if av_sf is None: continue + fp_sf: mlirlite.Value* = mlirlite.build_gep_struct(builder, struct_ty, fe_sf.Ty, storage_ptr, fe_sf.Index) + if fp_sf is None: continue + av_sf = self.Gen.ExprGenBase.coerce_to_type(builder, av_sf, fe_sf.Ty, arg_sf) + mlirlite.build_store(builder, av_sf, fp_sf, gc_volatile) return storage_ptr \ No newline at end of file