Skip to content

Commit 1c71634

Browse files
TysonAndrenikic
authored andcommitted
Fix generating signature types of AST_ARROW_FUNC
The return/parameter types would have incorrect AST nodes generated due to the param/return type check not being added for AST_ARROW_FUNC. Fixes nikic#121
1 parent ae71ecc commit 1c71634

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

ast.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ static inline zend_bool ast_is_name(zend_ast *ast, zend_ast *parent, uint32_t i)
355355

356356
if (i == 3) {
357357
return parent->kind == ZEND_AST_FUNC_DECL || parent->kind == ZEND_AST_CLOSURE
358+
#if PHP_VERSION_ID >= 70400
359+
|| parent->kind == ZEND_AST_ARROW_FUNC
360+
#endif
358361
|| parent->kind == ZEND_AST_METHOD;
359362
}
360363

@@ -372,6 +375,9 @@ static inline zend_bool ast_is_type(zend_ast *ast, zend_ast *parent, uint32_t i)
372375
}
373376
if (i == 3) {
374377
return parent->kind == ZEND_AST_CLOSURE || parent->kind == ZEND_AST_FUNC_DECL
378+
#if PHP_VERSION_ID >= 70400
379+
|| parent->kind == ZEND_AST_ARROW_FUNC
380+
#endif
375381
|| parent->kind == ZEND_AST_METHOD;
376382
}
377383
return 0;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
--TEST--
2+
Arrow functions and types ('fn($x) => $x') in PHP 7.4
3+
--SKIPIF--
4+
<?php if (PHP_VERSION_ID < 70400) die('skip PHP >= 7.4 only'); ?>
5+
--FILE--
6+
<?php
7+
8+
require __DIR__ . '/../util.php';
9+
10+
$code = <<<'PHP'
11+
<?php
12+
static fn() : int => 1;
13+
fn(iterable $i) : array => [$i];
14+
fn(stdClass $param) : \stdClass => $param;
15+
fn(\stdClass $param) : stdClass => $param;
16+
PHP;
17+
18+
$node = ast\parse_code($code, $version=70);
19+
$version_70_repr = ast_dump($node);
20+
echo $version_70_repr . "\n";
21+
$node50 = ast\parse_code($code, $version=50);
22+
$version_50_repr = ast_dump($node50);
23+
echo "Same representation in version 50/70: ";
24+
var_export($version_50_repr == $version_70_repr);
25+
echo "\n";
26+
?>
27+
--EXPECT--
28+
AST_STMT_LIST
29+
0: AST_ARROW_FUNC
30+
flags: MODIFIER_STATIC (16)
31+
name: "{closure}"
32+
docComment: null
33+
params: AST_PARAM_LIST
34+
stmts: AST_RETURN
35+
expr: 1
36+
returnType: AST_TYPE
37+
flags: TYPE_LONG (4)
38+
__declId: 0
39+
1: AST_ARROW_FUNC
40+
flags: 0
41+
name: "{closure}"
42+
docComment: null
43+
params: AST_PARAM_LIST
44+
0: AST_PARAM
45+
flags: 0
46+
type: AST_TYPE
47+
flags: TYPE_ITERABLE (18)
48+
name: "i"
49+
default: null
50+
stmts: AST_RETURN
51+
expr: AST_ARRAY
52+
flags: ARRAY_SYNTAX_SHORT (3)
53+
0: AST_ARRAY_ELEM
54+
flags: 0
55+
value: AST_VAR
56+
name: "i"
57+
key: null
58+
returnType: AST_TYPE
59+
flags: TYPE_ARRAY (7)
60+
__declId: 1
61+
2: AST_ARROW_FUNC
62+
flags: 0
63+
name: "{closure}"
64+
docComment: null
65+
params: AST_PARAM_LIST
66+
0: AST_PARAM
67+
flags: 0
68+
type: AST_NAME
69+
flags: NAME_NOT_FQ (1)
70+
name: "stdClass"
71+
name: "param"
72+
default: null
73+
stmts: AST_RETURN
74+
expr: AST_VAR
75+
name: "param"
76+
returnType: AST_NAME
77+
flags: NAME_FQ (0)
78+
name: "stdClass"
79+
__declId: 2
80+
3: AST_ARROW_FUNC
81+
flags: 0
82+
name: "{closure}"
83+
docComment: null
84+
params: AST_PARAM_LIST
85+
0: AST_PARAM
86+
flags: 0
87+
type: AST_NAME
88+
flags: NAME_FQ (0)
89+
name: "stdClass"
90+
name: "param"
91+
default: null
92+
stmts: AST_RETURN
93+
expr: AST_VAR
94+
name: "param"
95+
returnType: AST_NAME
96+
flags: NAME_NOT_FQ (1)
97+
name: "stdClass"
98+
__declId: 3
99+
Same representation in version 50/70: true

0 commit comments

Comments
 (0)