From a2428ca5da64e19a63fba6eabf5508f997a3739c Mon Sep 17 00:00:00 2001 From: Sebastian Jeong Date: Mon, 17 Aug 2026 00:03:26 +0900 Subject: [PATCH] fix: enforce the try rule at every position SPEC.md allows `try` only inside a function returning an error union, but the check sat in the FE_N_EXPR_STMT case, so it only ever saw a bare `try e;` and walked past `var x = try e;` and `x = try e;`. Move it onto the try expression in check_expr and drop the statement-level copy. This could not land before M7: closing the hole forces m5/runtime.fe's `run` to return an error union, and value returns from `-> !T` need contextual success construction. That arrives with M7, and `run` is now `-> !i32`, so the rule can be enforced. Supersedes the SPEC.AUDIT.md entry that recorded the blockage. M1-M7: 183 passed. --- fec/src/check.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fec/src/check.c b/fec/src/check.c index 52a1999..415ffcb 100644 --- a/fec/src/check.c +++ b/fec/src/check.c @@ -871,6 +871,12 @@ static FeType *check_expr(FeCheckerState *s, FeNode *n) if (known(a) && !fe_type_is_integer(a)) err(c, n->loc, "unary '-' requires integer"); } else if (strcmp(op, "try") == 0) { + /* SPEC 6.4: try is only allowed inside a function returning an error + union. Checked on the expression rather than on the statement so + that it also covers `var x = try e;` and `x = try e;`, which the + statement-level check walked straight past. */ + if (!s->ret || s->ret->kind != FE_TYPE_ERROR_UNION) + err(c,n->loc,"try requires an enclosing error result"); if (a && a->kind==FE_TYPE_ERROR_UNION) a=a->error_value; else { @@ -1549,11 +1555,9 @@ static void check_stmt(FeCheckerState *s, FeNode *n) } break; case FE_N_EXPR_STMT: + /* The enclosing-error-result check lives on the try expression itself, + so a bare `try e;` needs nothing extra here. */ check_expr(s, n->a); - if (n->a && n->a->kind==FE_N_UNARY && n->a->text && - strcmp(n->a->text,"try")==0 && - (!s->ret || s->ret->kind!=FE_TYPE_ERROR_UNION)) - err(c,n->loc,"try requires an enclosing error result"); break; case FE_N_DEFER: ++s->defer_depth;