Skip to content

Commit bee80ed

Browse files
committed
Fix arrow function with never return type
Fixes GH-7900
1 parent b1575f9 commit bee80ed

File tree

4 files changed

+42
-3
lines changed

4 files changed

+42
-3
lines changed

Zend/tests/gh7900.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-7900: Arrow function with never return type compile-time errors
3+
--FILE--
4+
<?php
5+
6+
$x = fn(): never => throw new \Exception('Here');
7+
8+
try {
9+
var_dump($x());
10+
} catch (\Exception $e) {
11+
echo $e->getMessage(), "\n";
12+
}
13+
14+
try {
15+
assert((fn(): never => 42) && false);
16+
} catch (\Error $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
20+
?>
21+
--EXPECT--
22+
Here
23+
assert(fn(): never => 42 && false)

Zend/zend_ast.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,9 +1761,12 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
17611761
}
17621762
if (decl->child[2]) {
17631763
if (decl->kind == ZEND_AST_ARROW_FUNC) {
1764-
ZEND_ASSERT(decl->child[2]->kind == ZEND_AST_RETURN);
1764+
zend_ast *body = decl->child[2];
1765+
if (decl->child[2]->kind == ZEND_AST_RETURN) {
1766+
body = body->child[0];
1767+
}
17651768
smart_str_appends(str, " => ");
1766-
zend_ast_export_ex(str, decl->child[2]->child[0], 0, indent);
1769+
zend_ast_export_ex(str, body, 0, indent);
17671770
break;
17681771
}
17691772

Zend/zend_compile.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7349,6 +7349,19 @@ static void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel)
73497349
} else if (uses_ast) {
73507350
zend_compile_closure_uses(uses_ast);
73517351
}
7352+
7353+
if (ast->kind == ZEND_AST_ARROW_FUNC) {
7354+
bool needs_return = true;
7355+
if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
7356+
zend_arg_info *return_info = CG(active_op_array)->arg_info - 1;
7357+
needs_return = !ZEND_TYPE_CONTAINS_CODE(return_info->type, IS_NEVER);
7358+
}
7359+
if (needs_return) {
7360+
stmt_ast = zend_ast_create(ZEND_AST_RETURN, stmt_ast);
7361+
ast->child[2] = stmt_ast;
7362+
}
7363+
}
7364+
73527365
zend_compile_stmt(stmt_ast);
73537366

73547367
if (is_method) {

Zend/zend_language_parser.y

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ inline_function:
12231223
T_DOUBLE_ARROW backup_fn_flags backup_lex_pos expr backup_fn_flags
12241224
{ $$ = zend_ast_create_decl(ZEND_AST_ARROW_FUNC, $2 | $12, $1, $3,
12251225
zend_string_init("{closure}", sizeof("{closure}") - 1, 0), $5, NULL,
1226-
zend_ast_create(ZEND_AST_RETURN, $11), $7, NULL);
1226+
$11, $7, NULL);
12271227
((zend_ast_decl *) $$)->lex_pos = $10;
12281228
CG(extra_fn_flags) = $9; }
12291229
;

0 commit comments

Comments
 (0)