1--TEST--
2Intersection types in php 8.1
3--SKIPIF--
4<?php if (PHP_VERSION_ID < 80100) die('skip PHP >= 8.1 only'); ?>
5--FILE--
6<?php
7
8require __DIR__ . '/../util.php';
9
10$code = <<<'PHP'
11<?php
12class X {
13    public Countable&ArrayAccess&Traversable $arrayLike;
14    public function example(Throwable&Countable $tc): self&Countable {
15        throw $tc;
16    }
17}
18// Using iterable, int, etc are compilation errors, not parse errors - programs using the output of php-ast will have to check for unsupported primitive types
19// (Fatal error: Type int cannot be part of an intersection type)
20function this_is_a_compile_error(): iterable&Countable {}
21PHP;
22
23$node = ast\parse_code($code, $version=80);
24echo ast_dump($node), "\n";
25
26--EXPECTF--
27AST_STMT_LIST
28    0: AST_CLASS
29        name: "X"
30        docComment: null
31        extends: null
32        implements: null
33        stmts: AST_STMT_LIST
34            0: AST_PROP_GROUP
35                flags: MODIFIER_PUBLIC (%d)
36                type: AST_TYPE_INTERSECTION
37                    0: AST_NAME
38                        flags: NAME_NOT_FQ (%d)
39                        name: "Countable"
40                    1: AST_NAME
41                        flags: NAME_NOT_FQ (%d)
42                        name: "ArrayAccess"
43                    2: AST_NAME
44                        flags: NAME_NOT_FQ (%d)
45                        name: "Traversable"
46                props: AST_PROP_DECL
47                    0: AST_PROP_ELEM
48                        name: "arrayLike"
49                        default: null
50                        docComment: null
51                attributes: null
52            1: AST_METHOD
53                flags: MODIFIER_PUBLIC (%d)
54                name: "example"
55                docComment: null
56                params: AST_PARAM_LIST
57                    0: AST_PARAM
58                        type: AST_TYPE_INTERSECTION
59                            0: AST_NAME
60                                flags: NAME_NOT_FQ (%d)
61                                name: "Throwable"
62                            1: AST_NAME
63                                flags: NAME_NOT_FQ (%d)
64                                name: "Countable"
65                        name: "tc"
66                        default: null
67                        attributes: null
68                        docComment: null
69                stmts: AST_STMT_LIST
70                    0: AST_THROW
71                        expr: AST_VAR
72                            name: "tc"
73                returnType: AST_TYPE_INTERSECTION
74                    0: AST_NAME
75                        flags: NAME_NOT_FQ (%d)
76                        name: "self"
77                    1: AST_NAME
78                        flags: NAME_NOT_FQ (%d)
79                        name: "Countable"
80                attributes: null
81                __declId: 0
82        attributes: null
83        __declId: 1
84    1: AST_FUNC_DECL
85        name: "this_is_a_compile_error"
86        docComment: null
87        params: AST_PARAM_LIST
88        stmts: AST_STMT_LIST
89        returnType: AST_TYPE_INTERSECTION
90            0: AST_TYPE
91                flags: TYPE_ITERABLE (%d)
92            1: AST_NAME
93                flags: NAME_NOT_FQ (%d)
94                name: "Countable"
95        attributes: null
96        __declId: 2