Skip to content

Commit f5532bf

Browse files
authored
Support php 8.0's mixed type (nikic#156)
Fixes nikic#154 - We've preferred AST versions that are multiples of 10 for previous releases.
1 parent 34e55df commit f5532bf

File tree

7 files changed

+102
-7
lines changed

7 files changed

+102
-7
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ ast\flags\TYPE_OBJECT
270270
ast\flags\TYPE_NULL // php 8.0 union types
271271
ast\flags\TYPE_FALSE // php 8.0 union types
272272
ast\flags\TYPE_STATIC // php 8.0 static return type
273+
ast\flags\TYPE_MIXED // php 8.0 mixed type
273274
274275
// Used by ast\AST_CAST (exclusive)
275276
ast\flags\TYPE_NULL
@@ -477,6 +478,12 @@ function accepts a boolean argument that determines whether deprecated versions
477478
In the following the changes in the respective AST versions, as well as their current support state,
478479
are listed.
479480

481+
### 80 (experimental)
482+
483+
Available since 1.0.7 (XXX).
484+
485+
* `mixed` type hints are now reported as an `AST_TYPE` with type `TYPE_MIXED` instead of an `AST_NAME`.
486+
480487
### 70 (current)
481488

482489
Supported since 1.0.1 (2019-02-11).

ast.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
/* Make IS_STATIC follow IS_ITERABLE in php 7.0 */
6565
#if PHP_VERSION_ID < 80000
6666
# define IS_STATIC 20
67+
# define IS_MIXED 21
6768
#endif
6869

6970
/* This contains state of the ast Node creator. */
@@ -122,6 +123,7 @@ static const char *type_flags[] = {
122123
AST_FLAG(TYPE_VOID),
123124
AST_FLAG(TYPE_ITERABLE),
124125
AST_FLAG(TYPE_STATIC),
126+
AST_FLAG(TYPE_MIXED),
125127
NULL
126128
};
127129

@@ -466,6 +468,8 @@ static const builtin_type_info builtin_types[] = {
466468
{ZEND_STRL("object"), IS_OBJECT},
467469
{ZEND_STRL("null"), IS_NULL}, /* Null and false for php 8.0 union types */
468470
{ZEND_STRL("false"), IS_FALSE},
471+
// {ZEND_STRL("static"), IS_STATIC}, /* Impossible to be parsed before php 8 */
472+
{ZEND_STRL("mixed"), IS_MIXED},
469473
{NULL, 0, IS_UNDEF}
470474
};
471475
static inline zend_uchar lookup_builtin_type(const zend_string *name) {
@@ -580,6 +584,7 @@ static inline void ast_name_to_zval(zend_ast *child, zend_ast *ast, zval *child_
580584
if (child->attr == ZEND_NAME_NOT_FQ
581585
&& ast_is_type(child, ast, i)
582586
&& (type = lookup_builtin_type(zend_ast_get_str(child)))
587+
&& (type != IS_MIXED || state->version >= 80)
583588
) {
584589
/* Convert "int" etc typehints to TYPE nodes */
585590
ast_create_virtual_node_ex(
@@ -881,7 +886,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
881886
#endif
882887
}
883888

884-
static const zend_long versions[] = {50, 60, 70};
889+
static const zend_long versions[] = {50, 60, 70, 80};
885890
static const size_t versions_count = sizeof(versions)/sizeof(versions[0]);
886891

887892
static inline zend_bool ast_version_deprecated(zend_long version) {
@@ -1291,6 +1296,7 @@ PHP_MINIT_FUNCTION(ast) {
12911296
ast_register_flag_constant("TYPE_VOID", IS_VOID);
12921297
ast_register_flag_constant("TYPE_ITERABLE", IS_ITERABLE);
12931298
ast_register_flag_constant("TYPE_STATIC", IS_STATIC);
1299+
ast_register_flag_constant("TYPE_MIXED", IS_MIXED);
12941300

12951301
ast_register_flag_constant("UNARY_BOOL_NOT", ZEND_BOOL_NOT);
12961302
ast_register_flag_constant("UNARY_BITWISE_NOT", ZEND_BW_NOT);

ast_stub.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@
129129
const PARAM_VARIADIC = 2;
130130
const TYPE_NULL = 1;
131131
const TYPE_FALSE = 2;
132-
const TYPE_BOOL = 16;
132+
const TYPE_BOOL = 17;
133133
const TYPE_LONG = 4;
134134
const TYPE_DOUBLE = 5;
135135
const TYPE_STRING = 6;
@@ -139,6 +139,7 @@
139139
const TYPE_VOID = 14;
140140
const TYPE_ITERABLE = 13;
141141
const TYPE_STATIC = 15;
142+
const TYPE_MIXED = 16;
142143
const UNARY_BOOL_NOT = 14;
143144
const UNARY_BITWISE_NOT = 13;
144145
const UNARY_SILENCE = 260;

package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
</stability>
3030
<license uri="https://github.com/nikic/php-ast/blob/master/LICENSE">BSD-3-Clause</license>
3131
<notes>
32-
- Support TYPE_STATIC for the php 8.0 static return type.
32+
- Add the experimental version 80, which returns `mixed` types as an `AST_TYPE` with type `TYPE_MIXED` instead of an `AST_NAME`.
3333
</notes>
3434
<contents>
3535
<dir name="/">

tests/get_supported_versions.phpt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,23 @@ var_dump(ast\get_supported_versions(true));
88

99
?>
1010
--EXPECT--
11-
array(3) {
11+
array(4) {
1212
[0]=>
1313
int(50)
1414
[1]=>
1515
int(60)
1616
[2]=>
1717
int(70)
18+
[3]=>
19+
int(80)
1820
}
19-
array(3) {
21+
array(4) {
2022
[0]=>
2123
int(50)
2224
[1]=>
2325
int(60)
2426
[2]=>
2527
int(70)
28+
[3]=>
29+
int(80)
2630
}

tests/metadata.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ AST_METHOD: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE,
5151
AST_ARROW_FUNC: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE, MODIFIER_STATIC, MODIFIER_ABSTRACT, MODIFIER_FINAL, FUNC_RETURNS_REF, FUNC_GENERATOR]
5252
AST_CLASS: [CLASS_ABSTRACT, CLASS_FINAL, CLASS_TRAIT, CLASS_INTERFACE, CLASS_ANONYMOUS]
5353
AST_MAGIC_CONST: [MAGIC_LINE, MAGIC_FILE, MAGIC_DIR, MAGIC_NAMESPACE, MAGIC_FUNCTION, MAGIC_METHOD, MAGIC_CLASS, MAGIC_TRAIT]
54-
AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC]
54+
AST_TYPE: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED]
5555
AST_VAR: []
5656
AST_CONST: []
5757
AST_UNPACK: []
58-
AST_CAST: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC]
58+
AST_CAST: [TYPE_NULL, TYPE_FALSE, TYPE_BOOL, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT, TYPE_CALLABLE, TYPE_VOID, TYPE_ITERABLE, TYPE_STATIC, TYPE_MIXED]
5959
AST_EMPTY: []
6060
AST_ISSET: []
6161
AST_SHELL_EXEC: []

tests/mixed_type.phpt

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
--TEST--
2+
Mixed types in PHP 8.0
3+
--FILE--
4+
<?php
5+
6+
require __DIR__ . '/../util.php';
7+
8+
$code = <<<'PHP'
9+
<?php
10+
class Xyz {
11+
public function test(mixed $x) : mixed {
12+
return $this;
13+
}
14+
}
15+
PHP;
16+
17+
$node = ast\parse_code($code, $version=70);
18+
echo ast_dump($node), "\n";
19+
$node = ast\parse_code($code, $version=80);
20+
echo ast_dump($node), "\n";
21+
--EXPECTF--
22+
AST_STMT_LIST
23+
0: AST_CLASS
24+
flags: 0
25+
name: "Xyz"
26+
docComment: null
27+
extends: null
28+
implements: null
29+
stmts: AST_STMT_LIST
30+
0: AST_METHOD
31+
flags: MODIFIER_PUBLIC (%d)
32+
name: "test"
33+
docComment: null
34+
params: AST_PARAM_LIST
35+
0: AST_PARAM
36+
flags: 0
37+
type: AST_NAME
38+
flags: NAME_NOT_FQ (1)
39+
name: "mixed"
40+
name: "x"
41+
default: null
42+
stmts: AST_STMT_LIST
43+
0: AST_RETURN
44+
expr: AST_VAR
45+
name: "this"
46+
returnType: AST_NAME
47+
flags: NAME_NOT_FQ (1)
48+
name: "mixed"
49+
__declId: 0
50+
__declId: 1
51+
AST_STMT_LIST
52+
0: AST_CLASS
53+
flags: 0
54+
name: "Xyz"
55+
docComment: null
56+
extends: null
57+
implements: null
58+
stmts: AST_STMT_LIST
59+
0: AST_METHOD
60+
flags: MODIFIER_PUBLIC (%d)
61+
name: "test"
62+
docComment: null
63+
params: AST_PARAM_LIST
64+
0: AST_PARAM
65+
flags: 0
66+
type: AST_TYPE
67+
flags: TYPE_MIXED (%d)
68+
name: "x"
69+
default: null
70+
stmts: AST_STMT_LIST
71+
0: AST_RETURN
72+
expr: AST_VAR
73+
name: "this"
74+
returnType: AST_TYPE
75+
flags: TYPE_MIXED (%d)
76+
__declId: 0
77+
__declId: 1

0 commit comments

Comments
 (0)