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:
+8
-4
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user