From a3a627f5134b01765976ff2a2b29e5ccb04149e0 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 10 Oct 2026 10:46:51 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20lambda=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=AE=8C=E5=85=A8=E8=B7=9F=E9=9A=8F=20body?= =?UTF-8?q?=EF=BC=88=E6=95=B4=E6=95=B0=E4=B9=9F=E8=B7=9F=E9=9A=8F=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E4=B8=80=E5=BE=8B=20i32=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 承接上一提交:原来只修正指针/浮点两类,整数仍保留 i32 语义(i64 实参会被 trunc 成 i32,静默有损)。现按用户要求改为**完全跟随 body 的实际类型**: - func.RetTy = body_val.Ty,然后原样 build_ret,不做任何强转; - void body(如 lambda: )→ RetTy = Void + build_ret_void (原来会因 "a void value cannot take part in any operation" 直接报错)。 副作用(预期内):body 为 bool → i1;body 为 i64/u64/f64 → 同宽返回;指针 → 指针。 调用点从函数签名取返回类型(CallGenMixin 读 local_fn.RetTy),自动适配。 注意:这是 ABI 行为变更,重编后必须回归 ClosureTest / ClosureTest2 / ClosureCallTest。 --- App/lib/core/Gen/Func/FuncGenMixin.vp | 38 ++++++++++----------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index 7f161f3..357d3e3 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -1035,35 +1035,25 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): self.Gen.VarGen.define_var(trans.SymTab, param_names + pi3 * 32, arg_alloca) # 11. Translate the body expression and return it. - # 返回类型:提升函数创建时(第 4 步)只能先写 i32——那时 body 还没翻译、拿不到类型。 - # 这里按 body 的**实际类型**修正 `func.RetTy`(mlirlite 公开字段;函数体只在本步发一条 ret, - # 期间没有任何人读 RetTy;调用点取签名时读到的已是修正后的类型)。 - # 修的是两类 i32 **无法表达**的情形(与嵌套 def 那条缺口同类): - # · 指针 → 原路径 coerce_to_type(ptr → i32) 直接 CastError(pointer→integer 禁止); - # · 浮点 → 原路径 fptosi 成 i32(静默有损)。 - # 整数/其它**保持既有 i32 语义**(与"无注解的嵌套 def 保持 i32"同口径,避免改动既有行为)。 + # 返回类型**完全跟随 body 的实际类型**:提升函数创建时(第 4 步)只能先写 i32——那时 body + # 还没翻译、拿不到类型。这里按 body 类型修正 `func.RetTy`(mlirlite 公开字段;本步之后才发 + # ret,期间没有任何人读 RetTy;调用点取签名时读到的已是修正后的类型),然后**原样返回、 + # 不再强转**。修正了原实现(一律 coerce 到 i32)的三类错法: + # · 指针 → coerce_to_type(ptr → i32) 直接 CastError(pointer→integer 禁止); + # · 浮点 → fptosi 成 i32(静默有损); + # · 更宽整数等 → trunc 成 i32(静默有损,如 i64 实参)。 + # void body(如 `lambda: `)→ 提升函数返回 void 并发 ret void + # (原来会因 "a void value cannot take part in any operation" 直接报错)。 body_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(func_builder, pool, mod, lam.body, None, 0, trans) if body_val is None or body_val.Ty is None: # fail-fast: lambda body translation failed; do not silently return 0 self.Gen.TypeGenErr.fatal_error(lam.body, "lambda body expression translation failed", "TypeError") + elif self.Gen.StmtGenDecl._is_void_type(body_val.Ty) != 0: + func.RetTy = body_val.Ty + mlirlite.build_ret_void(func_builder) else: - lam_ret_fixed: int = 0 - if self.Gen.ExprGenBase.is_ptr_type(body_val.Ty) != 0: - func.RetTy = body_val.Ty - mlirlite.build_ret(func_builder, body_val) - lam_ret_fixed = 1 - elif self.Gen.ExprGenBase.get_llvm_float_bits(body_val.Ty) != 0: - func.RetTy = body_val.Ty - mlirlite.build_ret(func_builder, body_val) - lam_ret_fixed = 1 - if lam_ret_fixed == 0: - if self.Gen.ExprGenBase.get_llvm_type_bits(body_val.Ty) == 32 and self.Gen.ExprGenBase.is_ptr_type(body_val.Ty) == 0: mlirlite.build_ret(func_builder, body_val) - else: - ret_val: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(func_builder, body_val, i32_ty, lam.body) - if ret_val is not None: mlirlite.build_ret(func_builder, ret_val) - else: - # fail-fast: lambda body coercion failed; do not silently return 0 - self.Gen.TypeGenErr.fatal_error(lam.body, "lambda body expression translation failed", "TypeError") + func.RetTy = body_val.Ty + mlirlite.build_ret(func_builder, body_val) # 12. Leave the lambda scope and restore the parent state self.Gen.VarGen.exit_scope(trans.SymTab)