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.
This commit is contained in:
2026-08-17 00:03:26 +09:00
parent 6713a934f5
commit a2428ca5da
+8 -4
View File
@@ -871,6 +871,12 @@ static FeType *check_expr(FeCheckerState *s, FeNode *n)
if (known(a) && !fe_type_is_integer(a)) if (known(a) && !fe_type_is_integer(a))
err(c, n->loc, "unary '-' requires integer"); err(c, n->loc, "unary '-' requires integer");
} else if (strcmp(op, "try") == 0) { } 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) if (a && a->kind==FE_TYPE_ERROR_UNION)
a=a->error_value; a=a->error_value;
else { else {
@@ -1549,11 +1555,9 @@ static void check_stmt(FeCheckerState *s, FeNode *n)
} }
break; break;
case FE_N_EXPR_STMT: 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); 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; break;
case FE_N_DEFER: case FE_N_DEFER:
++s->defer_depth; ++s->defer_depth;