Skip to content

Commit f957e3e

Browse files
committed
Fix arrow function with never return type
Fixes GH-7900 Closes GH-9103
1 parent 2152bb2 commit f957e3e

File tree

5 files changed

+49
-4
lines changed

5 files changed

+49
-4
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ PHP NEWS
4747
. Fixed bug #65069 (GlobIterator incorrect handling of open_basedir check).
4848
(Jakub Zelenka)
4949

50+
- Core:
51+
. Fixed bug GH-7900 (Arrow function with never return type compile-time
52+
errors). (ilutov)
53+
5054
21 Jul 2022, PHP 8.2.0beta1
5155

5256
- CLI:

Zend/tests/gh7900.phpt

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

Zend/zend_ast.c

+5-2
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 (body->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

+13
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+
decl->child[2] = stmt_ast;
7362+
}
7363+
}
7364+
73527365
zend_compile_stmt(stmt_ast);
73537366

73547367
if (is_method) {

Zend/zend_language_parser.y

+1-2
Original file line numberDiff line numberDiff line change
@@ -1222,8 +1222,7 @@ inline_function:
12221222
| fn returns_ref backup_doc_comment '(' parameter_list ')' return_type
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,
1225-
zend_string_init("{closure}", sizeof("{closure}") - 1, 0), $5, NULL,
1226-
zend_ast_create(ZEND_AST_RETURN, $11), $7, NULL);
1225+
zend_string_init("{closure}", sizeof("{closure}") - 1, 0), $5, NULL, $11, $7, NULL);
12271226
((zend_ast_decl *) $$)->lex_pos = $10;
12281227
CG(extra_fn_flags) = $9; }
12291228
;

0 commit comments

Comments
 (0)